mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-04-02 19:50:13 +02:00
DC mode timer sync STM32 and JL command
This commit is contained in:
parent
f3b87877ef
commit
5d1b3a7a03
@ -2,7 +2,7 @@
|
||||
* © 2022 Paul M Antoine
|
||||
* © 2021 Neil McKechnie
|
||||
* © 2021 Mike S
|
||||
* © 2021-2024 Herb Morton
|
||||
* © 2021-2025 Herb Morton
|
||||
* © 2020-2023 Harald Barth
|
||||
* © 2020-2021 M Steve Todd
|
||||
* © 2020-2021 Fred Decker
|
||||
@ -788,6 +788,11 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||
TrackManager::reportCurrent(stream); // <g limit...limit>
|
||||
return;
|
||||
|
||||
case "L"_hk: // <JL display row> track state and mA value on display
|
||||
if (params<3) break;
|
||||
TrackManager::reportCurrentLCD(p[1], p[2]); // Track power status
|
||||
return;
|
||||
|
||||
case "A"_hk: // <JA> intercepted by EXRAIL// <JA> returns automations/routes
|
||||
if (params!=1) break; // <JA>
|
||||
StringFormatter::send(stream, F("<jA>\n"));
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* © 2023 Neil McKechnie
|
||||
* © 2022-2024 Paul M. Antoine
|
||||
* © 2025 Herb Morton
|
||||
* © 2021 Mike S
|
||||
* © 2021, 2023 Harald Barth
|
||||
* © 2021 Fred Decker
|
||||
@ -36,6 +37,17 @@
|
||||
#include "DIAG.h"
|
||||
#include <wiring_private.h>
|
||||
|
||||
// Function prototypes
|
||||
void refreshDCmodeTimers();
|
||||
void resetCounterDCmodeTimers();
|
||||
|
||||
HardwareTimer *Timer1 = new HardwareTimer(TIM1);
|
||||
HardwareTimer *Timer4 = new HardwareTimer(TIM4);
|
||||
HardwareTimer *Timer9 = new HardwareTimer(TIM9);
|
||||
#if defined(TIM13)
|
||||
HardwareTimer *Timer13 = new HardwareTimer(TIM13);
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_NUCLEO_F401RE)
|
||||
// Nucleo-64 boards don't have additional serial ports defined by default
|
||||
// Serial1 is available on the F401RE, but not hugely convenient.
|
||||
@ -290,7 +302,7 @@ void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) {
|
||||
else if (f >= 3)
|
||||
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 16000);
|
||||
else if (f >= 2)
|
||||
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3400);
|
||||
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3600);
|
||||
else if (f == 1)
|
||||
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480);
|
||||
else
|
||||
@ -329,6 +341,7 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t frequency
|
||||
{
|
||||
pin_timer[pin]->setPWM(pin_channel[pin], pin, frequency, 0); // set frequency in Hertz, 0% dutycycle
|
||||
DIAG(F("DCCEXanalogWriteFrequency::Pin %d on Timer Channel %d, frequency %d"), pin, pin_channel[pin], frequency);
|
||||
resetCounterDCmodeTimers();
|
||||
}
|
||||
else
|
||||
DIAG(F("DCCEXanalogWriteFrequency::failed to allocate HardwareTimer instance!"));
|
||||
@ -341,6 +354,7 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t frequency
|
||||
pinmap_pinout(digitalPinToPinName(pin), PinMap_TIM); // ensure the pin has been configured!
|
||||
pin_timer[pin]->setOverflow(frequency, HERTZ_FORMAT); // Just change the frequency if it's already running!
|
||||
DIAG(F("DCCEXanalogWriteFrequency::setting frequency to %d"), frequency);
|
||||
resetCounterDCmodeTimers();
|
||||
}
|
||||
}
|
||||
channel_frequency[pin] = frequency;
|
||||
@ -365,6 +379,9 @@ void DCCTimer::DCCEXanalogWrite(uint8_t pin, int value, bool invert) {
|
||||
pin_timer[pin]->setCaptureCompare(pin_channel[pin], duty_cycle, PERCENT_COMPARE_FORMAT); // DCC_EX_PWM_FREQ Hertz, duty_cycle% dutycycle
|
||||
DIAG(F("DCCEXanalogWrite::Pin %d, value %d, duty cycle %d"), pin, value, duty_cycle);
|
||||
// }
|
||||
|
||||
refreshDCmodeTimers();
|
||||
resetCounterDCmodeTimers();
|
||||
}
|
||||
else
|
||||
DIAG(F("DCCEXanalogWrite::Pin %d is not configured for PWM!"), pin);
|
||||
@ -659,4 +676,31 @@ void ADCee::begin() {
|
||||
#endif
|
||||
interrupts();
|
||||
}
|
||||
|
||||
// NOTE: additional testing is needed to check the DCC signal
|
||||
// where the DCC signal pin is a pwm pin on timers 1, 4, 9, 13
|
||||
// or the brake pin is defined on a different timer.
|
||||
// -- example: F411RE/F446RE - pin 10 on stacked EX8874
|
||||
// lines added to sync timers --
|
||||
// not exact sync, but timers with the same frequency should be in sync
|
||||
void refreshDCmodeTimers() {
|
||||
Timer1->refresh();
|
||||
Timer4->refresh();
|
||||
Timer9->refresh();
|
||||
#if defined(TIM13)
|
||||
Timer13->refresh();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Function to synchronize timers - called every time there is powerON commmand for any DC track
|
||||
void resetCounterDCmodeTimers() {
|
||||
// Reset the counter for all DC mode timers
|
||||
TIM1->CNT = 0;
|
||||
TIM4->CNT = 0;
|
||||
TIM9->CNT = 0;
|
||||
#if defined(TIM13)
|
||||
TIM13->CNT = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,7 @@
|
||||
/*
|
||||
* © 2024, Chris Harlow. All rights reserved.
|
||||
* © 2024, Chris Harlow.
|
||||
* © 2025 Herb Morton
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of CommandStation-EX
|
||||
*
|
||||
@ -35,4 +37,4 @@ It has been moved here to be easier to maintain than editing IODevice.h
|
||||
#include "IO_EXSensorCAM.h"
|
||||
#include "IO_DS1307.h"
|
||||
#include "IO_I2CRailcom.h"
|
||||
|
||||
#include "IO_HALDisplay.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* © 2022-2024 Paul M Antoine
|
||||
* © 2024 Herb Morton
|
||||
* © 2024-2025 Herb Morton
|
||||
* © 2021 Mike S
|
||||
* © 2021 Fred Decker
|
||||
* © 2020-2023 Harald Barth
|
||||
@ -371,8 +371,8 @@ void MotorDriver::setDCSignal(byte speedcode, uint8_t frequency /*default =0*/)
|
||||
}
|
||||
#endif
|
||||
//DIAG(F("Brake pin %d value %d freqency %d"), brakePin, brake, f);
|
||||
DCCTimer::DCCEXanalogWrite(brakePin, brake, invertBrake);
|
||||
DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency
|
||||
DCCTimer::DCCEXanalogWrite(brakePin, brake, invertBrake); // line swapped to set frequency first
|
||||
#else // all AVR here
|
||||
DCCTimer::DCCEXanalogWriteFrequency(brakePin, frequency); // frequency steps
|
||||
analogWrite(brakePin, invertBrake ? 255-brake : brake);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* © 2022-2025 Chris Harlow
|
||||
* © 2022-2024 Harald Barth
|
||||
* © 2023-2024 Paul M. Antoine
|
||||
* © 2024 Herb Morton
|
||||
* © 2024-2025 Herb Morton
|
||||
* © 2023 Colin Murdoch
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -42,6 +42,7 @@
|
||||
|
||||
MotorDriver * TrackManager::track[MAX_TRACKS] = { NULL };
|
||||
int16_t TrackManager::trackDCAddr[MAX_TRACKS] = { 0 };
|
||||
int16_t TrackManager::tPwr_mA[8]={0,0,0,0,0,0,0,0};
|
||||
|
||||
int8_t TrackManager::lastTrack=-1;
|
||||
bool TrackManager::progTrackSyncMain=false;
|
||||
@ -646,6 +647,33 @@ void TrackManager::reportCurrent(Print* stream) {
|
||||
StringFormatter::send(stream,F(">\n"));
|
||||
}
|
||||
|
||||
void TrackManager::reportCurrentLCD(uint8_t display, byte row) {
|
||||
FOR_EACH_TRACK(t) {
|
||||
bool pstate = TrackManager::isPowerOn(t); // checks if power is on or off
|
||||
TRACK_MODE tMode=(TrackManager::getMode(t)); // gets to current power mode
|
||||
int16_t DCAddr=(TrackManager::returnDCAddr(t));
|
||||
|
||||
if (pstate) { // if power is on do this section
|
||||
tPwr_mA[t]=(3*tPwr_mA[t]>>2) + ((track[t]->getPower()==POWERMODE::OVERLOAD) ? -1 :
|
||||
track[t]->raw2mA(track[t]->getCurrentRaw(false)));
|
||||
if (tMode & TRACK_MODE_DC) { // Test if track is in DC or DCX mode
|
||||
SCREEN(display, row+t, F("%c: %S %d ON %dmA"), t+'A', (TrackManager::getModeName(tMode)),DCAddr, tPwr_mA[t]>>2);
|
||||
}
|
||||
else { // formats without DCAddress
|
||||
SCREEN(display, row+t, F("%c: %S ON %dmA"), t+'A', (TrackManager::getModeName(tMode)), tPwr_mA[t]>>2);
|
||||
}
|
||||
}
|
||||
/* else { // if power is off do this section
|
||||
if (tMode & TRACK_MODE_DC) { // DC / DCX
|
||||
SCREEN(display, row+t, F("Track %c: %S %d OFF"), t+'A', (TrackManager::getModeName(tMode)),DCAddr);
|
||||
}
|
||||
else { // Not DC or DCX
|
||||
SCREEN(display, row+t, F("Track %c: %S OFF"), t+'A', (TrackManager::getModeName(tMode)));
|
||||
}
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
void TrackManager::reportGauges(Print* stream) {
|
||||
StringFormatter::send(stream,F("<jG"));
|
||||
FOR_EACH_TRACK(t) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* © 2022 Chris Harlow
|
||||
* © 2022-2024 Harald Barth
|
||||
* © 2025 Herb Morton
|
||||
* © 2023 Colin Murdoch
|
||||
*
|
||||
* All rights reserved.
|
||||
@ -87,6 +88,7 @@ class TrackManager {
|
||||
static void sampleCurrent();
|
||||
static void reportGauges(Print* stream);
|
||||
static void reportCurrent(Print* stream);
|
||||
static void reportCurrentLCD(uint8_t display, byte row);
|
||||
static void reportObsoleteCurrent(Print* stream);
|
||||
static void streamTrackState(Print* stream, byte t);
|
||||
static bool isPowerOn(byte t);
|
||||
@ -105,6 +107,7 @@ class TrackManager {
|
||||
private:
|
||||
#endif
|
||||
static MotorDriver* track[MAX_TRACKS];
|
||||
static int16_t tPwr_mA[8]; // for <JL ..> command
|
||||
|
||||
private:
|
||||
static void addTrack(byte t, MotorDriver* driver);
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
#include "StringFormatter.h"
|
||||
|
||||
#define VERSION "5.5.12"
|
||||
#define VERSION "5.5.12 F439"
|
||||
// - Nucleo-F4 DC mode timer sync
|
||||
// - <JL display startRow> Track power status
|
||||
// 5.5.12 - Websocket support (wifi only)
|
||||
// 5.5.11 - (5.4.2) accessory command reverse
|
||||
// 5.5.10 - CamParser fix
|
||||
|
Loading…
Reference in New Issue
Block a user