mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-02-19 23:46:02 +01:00
Timer stuff with incomplete teensy
This commit is contained in:
parent
dd9152864b
commit
6fc223d80b
@ -147,7 +147,7 @@ void loop()
|
|||||||
// Report any decrease in memory (will automatically trigger on first call)
|
// Report any decrease in memory (will automatically trigger on first call)
|
||||||
static int ramLowWatermark = __INT_MAX__; // replaced on first loop
|
static int ramLowWatermark = __INT_MAX__; // replaced on first loop
|
||||||
|
|
||||||
int freeNow = minimumFreeMemory();
|
int freeNow = DCCTimer::getMinimumFreeMemory();
|
||||||
if (freeNow < ramLowWatermark) {
|
if (freeNow < ramLowWatermark) {
|
||||||
ramLowWatermark = freeNow;
|
ramLowWatermark = freeNow;
|
||||||
LCD(3,F("Free RAM=%5db"), ramLowWatermark);
|
LCD(3,F("Free RAM=%5db"), ramLowWatermark);
|
||||||
|
2
DCCEX.h
2
DCCEX.h
@ -38,7 +38,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "LCD_Implementation.h"
|
#include "LCD_Implementation.h"
|
||||||
#include "LCN.h"
|
#include "LCN.h"
|
||||||
#include "freeMemory.h"
|
|
||||||
#include "IODevice.h"
|
#include "IODevice.h"
|
||||||
#include "Turnouts.h"
|
#include "Turnouts.h"
|
||||||
#include "Sensors.h"
|
#include "Sensors.h"
|
||||||
@ -46,4 +45,5 @@
|
|||||||
#include "EXRAIL.h"
|
#include "EXRAIL.h"
|
||||||
#include "CommandDistributor.h"
|
#include "CommandDistributor.h"
|
||||||
#include "TrackManager.h"
|
#include "TrackManager.h"
|
||||||
|
#include "DCCTimer.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include "Turnouts.h"
|
#include "Turnouts.h"
|
||||||
#include "Outputs.h"
|
#include "Outputs.h"
|
||||||
#include "Sensors.h"
|
#include "Sensors.h"
|
||||||
#include "freeMemory.h"
|
|
||||||
#include "GITHUB_SHA.h"
|
#include "GITHUB_SHA.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
@ -38,6 +37,7 @@
|
|||||||
#include "EEStore.h"
|
#include "EEStore.h"
|
||||||
#include "DIAG.h"
|
#include "DIAG.h"
|
||||||
#include "TrackManager.h"
|
#include "TrackManager.h"
|
||||||
|
#include "DCCTimer.h"
|
||||||
#include <avr/wdt.h>
|
#include <avr/wdt.h>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -732,7 +732,7 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case HASH_KEYWORD_RAM: // <D RAM>
|
case HASH_KEYWORD_RAM: // <D RAM>
|
||||||
StringFormatter::send(stream, F("Free memory=%d\n"), minimumFreeMemory());
|
StringFormatter::send(stream, F("Free memory=%d\n"), DCCTimer::getMinimumFreeMemory());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HASH_KEYWORD_ACK: // <D ACK ON/OFF> <D ACK [LIMIT|MIN|MAX|RETRY] Value>
|
case HASH_KEYWORD_ACK: // <D ACK ON/OFF> <D ACK [LIMIT|MIN|MAX|RETRY] Value>
|
||||||
|
57
DCCTimer.h
57
DCCTimer.h
@ -20,6 +20,34 @@
|
|||||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* There are several different implementations of this class which the compiler will select
|
||||||
|
according to the hardware.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This timer class is used to manage the single timer required to handle the DCC waveform.
|
||||||
|
* All timer access comes through this class so that it can be compiled for
|
||||||
|
* various hardware CPU types.
|
||||||
|
*
|
||||||
|
* DCCEX works on a single timer interrupt at a regular 58uS interval.
|
||||||
|
* The DCCWaveform class generates the signals to the motor shield
|
||||||
|
* based on this timer.
|
||||||
|
*
|
||||||
|
* If the motor drivers are BOTH configured to use the correct 2 pins for the architecture,
|
||||||
|
* (see isPWMPin() function. )
|
||||||
|
* then this allows us to use a hardware driven pin switching arrangement which is
|
||||||
|
* achieved by setting the duty cycle of the NEXT clock interrupt to 0% or 100% depending on
|
||||||
|
* the required pin state. (see setPWM())
|
||||||
|
* This is more accurate than the software interrupt but at the expense of
|
||||||
|
* limiting the choice of available pins.
|
||||||
|
* Fortunately, a standard motor shield on a Mega uses pins that qualify for PWM...
|
||||||
|
* Other shields may be jumpered to PWM pins or run directly using the software interrupt.
|
||||||
|
*
|
||||||
|
* Because the PWM-based waveform is effectively set half a cycle after the software version,
|
||||||
|
* it is not acceptable to drive the two tracks on different methiods or it would cause
|
||||||
|
* problems for <1 JOIN> etc.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef DCCTimer_h
|
#ifndef DCCTimer_h
|
||||||
#define DCCTimer_h
|
#define DCCTimer_h
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
@ -32,11 +60,30 @@ class DCCTimer {
|
|||||||
static void getSimulatedMacAddress(byte mac[6]);
|
static void getSimulatedMacAddress(byte mac[6]);
|
||||||
static bool isPWMPin(byte pin);
|
static bool isPWMPin(byte pin);
|
||||||
static void setPWM(byte pin, bool high);
|
static void setPWM(byte pin, bool high);
|
||||||
#if (defined(TEENSYDUINO) && !defined(__IMXRT1062__))
|
|
||||||
static void read_mac(byte mac[6]);
|
// Update low ram level. Allow for extra bytes to be specified
|
||||||
static void read(uint8_t word, uint8_t *mac, uint8_t offset);
|
// by estimation or inspection, that may be used by other
|
||||||
#endif
|
// called subroutines. Must be called with interrupts disabled.
|
||||||
private:
|
//
|
||||||
|
// Although __brkval may go up and down as heap memory is allocated
|
||||||
|
// and freed, this function records only the worst case encountered.
|
||||||
|
// So even if all of the heap is freed, the reported minimum free
|
||||||
|
// memory will not increase.
|
||||||
|
//
|
||||||
|
static void inline updateMinimumFreeMemoryISR(unsigned char extraBytes=0) {
|
||||||
|
int spare = freeMemory()-extraBytes;
|
||||||
|
if (spare < 0) spare = 0;
|
||||||
|
if (spare < minimum_free_memory) minimum_free_memory = spare;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getMinimumFreeMemory();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int freeMemory();
|
||||||
|
static volatile int minimum_free_memory;
|
||||||
|
static const int DCC_SIGNAL_TIME=58; // this is the 58uS DCC 1-bit waveform half-cycle
|
||||||
|
static const long CLOCK_CYCLES=(F_CPU / 1000000 * DCC_SIGNAL_TIME) >>1;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
113
DCCTimerAVR.cpp
Normal file
113
DCCTimerAVR.cpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* © 2021 Mike S
|
||||||
|
* © 2021 Harald Barth
|
||||||
|
* © 2021 Fred Decker
|
||||||
|
* © 2021 Chris Harlow
|
||||||
|
* © 2021 David Cutting
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ATTENTION: this file only compiles on a UNO or MEGA
|
||||||
|
// Please refer to DCCTimer.h for general comments about how this class works
|
||||||
|
// This is to avoid repetition and duplication.
|
||||||
|
#ifdef ARDUINO_ARCH_AVR
|
||||||
|
|
||||||
|
#include <avr/boot.h>
|
||||||
|
#include "DCCTimer.h"
|
||||||
|
INTERRUPT_CALLBACK interruptHandler=0;
|
||||||
|
|
||||||
|
// Arduino nano, uno, mega etc
|
||||||
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
#define TIMER1_A_PIN 11
|
||||||
|
#define TIMER1_B_PIN 12
|
||||||
|
#define TIMER1_C_PIN 13
|
||||||
|
#else
|
||||||
|
#define TIMER1_A_PIN 9
|
||||||
|
#define TIMER1_B_PIN 10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
|
||||||
|
interruptHandler=callback;
|
||||||
|
noInterrupts();
|
||||||
|
ADCSRA = (ADCSRA & 0b11111000) | 0b00000100; // speed up analogRead sample time
|
||||||
|
TCCR1A = 0;
|
||||||
|
ICR1 = CLOCK_CYCLES;
|
||||||
|
TCNT1 = 0;
|
||||||
|
TCCR1B = _BV(WGM13) | _BV(CS10); // Mode 8, clock select 1
|
||||||
|
TIMSK1 = _BV(TOIE1); // Enable Software interrupt
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ISR called by timer interrupt every 58uS
|
||||||
|
ISR(TIMER1_OVF_vect){ interruptHandler(); }
|
||||||
|
|
||||||
|
// Alternative pin manipulation via PWM control.
|
||||||
|
bool DCCTimer::isPWMPin(byte pin) {
|
||||||
|
return pin==TIMER1_A_PIN
|
||||||
|
|| pin==TIMER1_B_PIN
|
||||||
|
#ifdef TIMER1_C_PIN
|
||||||
|
|| pin==TIMER1_C_PIN
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCCTimer::setPWM(byte pin, bool high) {
|
||||||
|
if (pin==TIMER1_A_PIN) {
|
||||||
|
TCCR1A |= _BV(COM1A1);
|
||||||
|
OCR1A= high?1024:0;
|
||||||
|
}
|
||||||
|
else if (pin==TIMER1_B_PIN) {
|
||||||
|
TCCR1A |= _BV(COM1B1);
|
||||||
|
OCR1B= high?1024:0;
|
||||||
|
}
|
||||||
|
#ifdef TIMER1_C_PIN
|
||||||
|
else if (pin==TIMER1_C_PIN) {
|
||||||
|
TCCR1A |= _BV(COM1C1);
|
||||||
|
OCR1C= high?1024:0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCCTimer::getSimulatedMacAddress(byte mac[6]) {
|
||||||
|
for (byte i=0; i<6; i++) {
|
||||||
|
mac[i]=boot_signature_byte_get(0x0E + i);
|
||||||
|
}
|
||||||
|
mac[0] &= 0xFE;
|
||||||
|
mac[0] |= 0x02;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
volatile int DCCTimer::minimum_free_memory=__INT_MAX__;
|
||||||
|
|
||||||
|
// Return low memory value...
|
||||||
|
int DCCTimer::getMinimumFreeMemory() {
|
||||||
|
noInterrupts(); // Disable interrupts to get volatile value
|
||||||
|
int retval = minimum_free_memory;
|
||||||
|
interrupts();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char *__brkval;
|
||||||
|
extern char *__malloc_heap_start;
|
||||||
|
|
||||||
|
int DCCTimer::freeMemory() {
|
||||||
|
char top;
|
||||||
|
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -47,14 +47,17 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// ATTENTION: this file only compiles on a UnoWifiRev3 or NanoEvery
|
||||||
|
// Please refer to DCCTimer.h for general comments about how this class works
|
||||||
|
// This is to avoid repetition and duplication.
|
||||||
|
#ifdef ARDUINO_ARCH_MEGAAVR
|
||||||
|
|
||||||
#include "DCCTimer.h"
|
#include "DCCTimer.h"
|
||||||
const int DCC_SIGNAL_TIME=58; // this is the 58uS DCC 1-bit waveform half-cycle
|
|
||||||
const long CLOCK_CYCLES=(F_CPU / 1000000 * DCC_SIGNAL_TIME) >>1;
|
|
||||||
|
|
||||||
INTERRUPT_CALLBACK interruptHandler=0;
|
INTERRUPT_CALLBACK interruptHandler=0;
|
||||||
|
extern char *__brkval;
|
||||||
|
extern char *__malloc_heap_start;
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_MEGAAVR
|
|
||||||
// Arduino unoWifi Rev2 and nanoEvery architectire
|
|
||||||
|
|
||||||
void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
|
void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
|
||||||
interruptHandler=callback;
|
interruptHandler=callback;
|
||||||
@ -93,126 +96,9 @@ INTERRUPT_CALLBACK interruptHandler=0;
|
|||||||
mac[0] |= 0x02;
|
mac[0] |= 0x02;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(TEENSYDUINO)
|
int DCCTimer::freeMemory() {
|
||||||
IntervalTimer myDCCTimer;
|
char top;
|
||||||
|
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
|
||||||
void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
|
|
||||||
interruptHandler=callback;
|
|
||||||
|
|
||||||
myDCCTimer.begin(interruptHandler, DCC_SIGNAL_TIME);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DCCTimer::isPWMPin(byte pin) {
|
|
||||||
//Teensy: 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]) {
|
|
||||||
#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__)
|
|
||||||
#define TIMER1_A_PIN 11
|
|
||||||
#define TIMER1_B_PIN 12
|
|
||||||
#define TIMER1_C_PIN 13
|
|
||||||
#else
|
|
||||||
#define TIMER1_A_PIN 9
|
|
||||||
#define TIMER1_B_PIN 10
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
|
|
||||||
interruptHandler=callback;
|
|
||||||
noInterrupts();
|
|
||||||
ADCSRA = (ADCSRA & 0b11111000) | 0b00000100; // speed up analogRead sample time
|
|
||||||
TCCR1A = 0;
|
|
||||||
ICR1 = CLOCK_CYCLES;
|
|
||||||
TCNT1 = 0;
|
|
||||||
TCCR1B = _BV(WGM13) | _BV(CS10); // Mode 8, clock select 1
|
|
||||||
TIMSK1 = _BV(TOIE1); // Enable Software interrupt
|
|
||||||
interrupts();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ISR called by timer interrupt every 58uS
|
|
||||||
ISR(TIMER1_OVF_vect){ interruptHandler(); }
|
|
||||||
|
|
||||||
// Alternative pin manipulation via PWM control.
|
|
||||||
bool DCCTimer::isPWMPin(byte pin) {
|
|
||||||
return pin==TIMER1_A_PIN
|
|
||||||
|| pin==TIMER1_B_PIN
|
|
||||||
#ifdef TIMER1_C_PIN
|
|
||||||
|| pin==TIMER1_C_PIN
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DCCTimer::setPWM(byte pin, bool high) {
|
|
||||||
if (pin==TIMER1_A_PIN) {
|
|
||||||
TCCR1A |= _BV(COM1A1);
|
|
||||||
OCR1A= high?1024:0;
|
|
||||||
}
|
|
||||||
else if (pin==TIMER1_B_PIN) {
|
|
||||||
TCCR1A |= _BV(COM1B1);
|
|
||||||
OCR1B= high?1024:0;
|
|
||||||
}
|
|
||||||
#ifdef TIMER1_C_PIN
|
|
||||||
else if (pin==TIMER1_C_PIN) {
|
|
||||||
TCCR1A |= _BV(COM1C1);
|
|
||||||
OCR1C= high?1024:0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#include <avr/boot.h>
|
|
||||||
void DCCTimer::getSimulatedMacAddress(byte mac[6]) {
|
|
||||||
for (byte i=0; i<6; i++) {
|
|
||||||
mac[i]=boot_signature_byte_get(0x0E + i);
|
|
||||||
}
|
|
||||||
mac[0] &= 0xFE;
|
|
||||||
mac[0] |= 0x02;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
122
DCCTimerTEENSY.cpp
Normal file
122
DCCTimerTEENSY.cpp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* © 2021 Mike S
|
||||||
|
* © 2021 Harald Barth
|
||||||
|
* © 2021 Fred Decker
|
||||||
|
* © 2021 Chris Harlow
|
||||||
|
* © 2021 David Cutting
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 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 TEENSYDUINO
|
||||||
|
|
||||||
|
#include "DCCTimer.h"
|
||||||
|
|
||||||
|
INTERRUPT_CALLBACK interruptHandler=0;
|
||||||
|
|
||||||
|
IntervalTimer myDCCTimer;
|
||||||
|
|
||||||
|
void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
|
||||||
|
interruptHandler=callback;
|
||||||
|
myDCCTimer.begin(interruptHandler, DCC_SIGNAL_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DCCTimer::isPWMPin(byte pin) {
|
||||||
|
//Teensy: 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__IMXRT1062__) //Teensy 4.0 and Teensy 4.1
|
||||||
|
void DCCTimer::getSimulatedMacAddress(byte mac[6]) {
|
||||||
|
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
|
||||||
|
|
||||||
|
// http://forum.pjrc.com/threads/91-teensy-3-MAC-address
|
||||||
|
void teensyRead(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.
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCCTimer::getSimulatedMacAddress(byte mac[6]) {
|
||||||
|
teensyRead(0xe,mac,0);
|
||||||
|
teensyRead(0xf,mac,3);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__IMXRT1062__)
|
||||||
|
static inline int freeMemory() {
|
||||||
|
char top;
|
||||||
|
return &top - reinterpret_cast<char*>(sbrk(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
@ -29,7 +29,7 @@
|
|||||||
#include "DCCTimer.h"
|
#include "DCCTimer.h"
|
||||||
#include "DCCACK.h"
|
#include "DCCACK.h"
|
||||||
#include "DIAG.h"
|
#include "DIAG.h"
|
||||||
#include "freeMemory.h"
|
|
||||||
|
|
||||||
DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true);
|
DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true);
|
||||||
DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false);
|
DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false);
|
||||||
@ -140,7 +140,7 @@ void DCCWaveform::interrupt2() {
|
|||||||
remainingPreambles--;
|
remainingPreambles--;
|
||||||
// Update free memory diagnostic as we don't have anything else to do this time.
|
// Update free memory diagnostic as we don't have anything else to do this time.
|
||||||
// Allow for checkAck and its called functions using 22 bytes more.
|
// Allow for checkAck and its called functions using 22 bytes more.
|
||||||
updateMinimumFreeMemory(22);
|
DCCTimer::updateMinimumFreeMemoryISR(22);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,9 +138,6 @@ 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() {
|
bool MotorDriver::canMeasureCurrent() {
|
||||||
return currentPin!=UNUSED_PIN;
|
return currentPin!=UNUSED_PIN;
|
||||||
|
@ -47,7 +47,6 @@ void TrackManager::Setup(const FSH * shieldname,
|
|||||||
MotorDriver * track0, MotorDriver * track1, MotorDriver * track2,
|
MotorDriver * track0, MotorDriver * track1, MotorDriver * track2,
|
||||||
MotorDriver * track3, MotorDriver * track4, MotorDriver * track5,
|
MotorDriver * track3, MotorDriver * track4, MotorDriver * track5,
|
||||||
MotorDriver * track6, MotorDriver * track7 ) {
|
MotorDriver * track6, MotorDriver * track7 ) {
|
||||||
(void) shieldname; // TODO
|
|
||||||
addTrack(0,track0);
|
addTrack(0,track0);
|
||||||
addTrack(1,track1);
|
addTrack(1,track1);
|
||||||
addTrack(2,track2);
|
addTrack(2,track2);
|
||||||
|
112
freeMemory.cpp
112
freeMemory.cpp
@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
* © 2021 Neil McKechnie
|
|
||||||
* © 2021 Mike S
|
|
||||||
* © 2020 Harald Barth
|
|
||||||
*
|
|
||||||
* This file is part of Asbelos DCC-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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include "freeMemory.h"
|
|
||||||
|
|
||||||
// thanks go to https://github.com/mpflaga/Arduino-MemoryFree
|
|
||||||
#if defined(__arm__)
|
|
||||||
extern "C" char* sbrk(int);
|
|
||||||
#elif defined(__AVR__)
|
|
||||||
extern char *__brkval;
|
|
||||||
extern char *__malloc_heap_start;
|
|
||||||
#else
|
|
||||||
#error Unsupported board type
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static volatile int minimum_free_memory = __INT_MAX__;
|
|
||||||
|
|
||||||
#if !defined(__IMXRT1062__)
|
|
||||||
static inline int freeMemory() {
|
|
||||||
char top;
|
|
||||||
#if defined(__arm__)
|
|
||||||
return &top - reinterpret_cast<char*>(sbrk(0));
|
|
||||||
#elif defined(__AVR__)
|
|
||||||
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
|
|
||||||
#else
|
|
||||||
#error bailed out already above
|
|
||||||
#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.
|
|
||||||
//
|
|
||||||
// Although __brkval may go up and down as heap memory is allocated
|
|
||||||
// and freed, this function records only the worst case encountered.
|
|
||||||
// So even if all of the heap is freed, the reported minimum free
|
|
||||||
// memory will not increase.
|
|
||||||
//
|
|
||||||
void updateMinimumFreeMemory(unsigned char extraBytes) {
|
|
||||||
int spare = freeMemory()-extraBytes;
|
|
||||||
if (spare < 0) spare = 0;
|
|
||||||
if (spare < minimum_free_memory) minimum_free_memory = spare;
|
|
||||||
}
|
|
||||||
|
|
25
freeMemory.h
25
freeMemory.h
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* © 2021 Neil McKechnie
|
|
||||||
* © 2020 Harald Barth
|
|
||||||
*
|
|
||||||
* This file is part of DCC-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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef freeMemory_h
|
|
||||||
#define freeMemory_h
|
|
||||||
void updateMinimumFreeMemory(unsigned char extraBytes=0);
|
|
||||||
int minimumFreeMemory();
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user