mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-04-20 20:21:18 +02:00
Compare commits
12 Commits
34c33f7ebf
...
ed087d22e1
Author | SHA1 | Date | |
---|---|---|---|
|
ed087d22e1 | ||
|
911bbd63be | ||
|
393b0bbd16 | ||
|
d9bd1e75f2 | ||
|
d1daf41f12 | ||
|
6bfa7028c4 | ||
|
a5d1d04882 | ||
|
bd6e426499 | ||
|
09bae44cc0 | ||
|
9f3354c687 | ||
|
fb495985f4 | ||
|
53f598192c |
85
.github/workflows/main.yml
vendored
85
.github/workflows/main.yml
vendored
@ -1,19 +1,82 @@
|
|||||||
name: CI
|
name: PlatformIO CI
|
||||||
|
|
||||||
on: [push]
|
on: [push]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Install Python Wheel
|
- uses: actions/cache@v3
|
||||||
run: pip install wheel
|
with:
|
||||||
- name: Install PlatformIO Core
|
path: |
|
||||||
run: pip install -U platformio
|
~/.cache/pip
|
||||||
- name: Copy generic config over
|
~/.platformio/.cache
|
||||||
run: cp config.example.h config.h
|
key: ${{ runner.os }}-pio
|
||||||
- name: Compile Command Station (AVR)
|
- uses: actions/setup-python@v4
|
||||||
run: python -m platformio run
|
with:
|
||||||
|
python-version: '3.9'
|
||||||
|
- name: Install PlatformIO Core
|
||||||
|
run: pip install --upgrade platformio
|
||||||
|
|
||||||
|
- name: Use sample "config.example.h" for compilations
|
||||||
|
run: mv $GITHUB_WORKSPACE/config.example.h $GITHUB_WORKSPACE/config.h
|
||||||
|
|
||||||
|
- name: Build PlatformIO Project
|
||||||
|
run: pio run
|
||||||
|
|
||||||
|
- name: Copy all firmwares for for packaging
|
||||||
|
run: |
|
||||||
|
mkdir downloads
|
||||||
|
cd .pio/build
|
||||||
|
find . -name '*.bin' | cpio -pdm ../../downloads
|
||||||
|
find . -name '*.hex' | cpio -pdm ../../downloads
|
||||||
|
find . -name '*.uf2' | cpio -pdm ../../downloads
|
||||||
|
cd ../..
|
||||||
|
|
||||||
|
- name: Package and upload all firmwares for download
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: all-firmwares-for-download
|
||||||
|
path: downloads
|
||||||
|
|
||||||
|
- name: Test on Arduino MEGA with Wokwi
|
||||||
|
uses: wokwi/wokwi-ci-action@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.WOKWI_CLI_TOKEN }}
|
||||||
|
path: /wokwi/mega # directory with wokwi.toml, relative to repo's root
|
||||||
|
timeout: 10000
|
||||||
|
expect_text: '<* LCD3:Free RAM='
|
||||||
|
fail_text: 'Error'
|
||||||
|
# scenario: 'test-hello-world.yaml' # optional
|
||||||
|
|
||||||
|
- name: Test on Arduino UNO with Wokwi
|
||||||
|
uses: wokwi/wokwi-ci-action@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.WOKWI_CLI_TOKEN }}
|
||||||
|
path: /wokwi/uno # directory with wokwi.toml, relative to repo's root
|
||||||
|
timeout: 10000
|
||||||
|
expect_text: '<* LCD3:Free RAM='
|
||||||
|
fail_text: 'Error'
|
||||||
|
# scenario: 'test-hello-world.yaml' # optional
|
||||||
|
|
||||||
|
- name: Test on Arduino NANO with Wokwi
|
||||||
|
uses: wokwi/wokwi-ci-action@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.WOKWI_CLI_TOKEN }}
|
||||||
|
path: /wokwi/nano # directory with wokwi.toml, relative to repo's root
|
||||||
|
timeout: 10000
|
||||||
|
expect_text: '<* LCD3:Free RAM='
|
||||||
|
fail_text: 'Error'
|
||||||
|
# scenario: 'test-hello-world.yaml' # optional
|
||||||
|
|
||||||
|
- name: Test on ESP32 with Wokwi
|
||||||
|
uses: wokwi/wokwi-ci-action@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.WOKWI_CLI_TOKEN }}
|
||||||
|
path: /wokwi/esp32 # directory with wokwi.toml, relative to repo's root
|
||||||
|
timeout: 10000
|
||||||
|
expect_text: 'ESP32 / STANDARD_MOTOR_SHIELD'
|
||||||
|
fail_text: 'Error'
|
||||||
|
# scenario: 'test-hello-world.yaml' # optional
|
||||||
|
@ -280,6 +280,9 @@ void CommandDistributor::broadcastPower() {
|
|||||||
state = '1';
|
state = '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state != '2')
|
||||||
|
broadcastReply(COMMAND_TYPE, F("<p%c>\n"),state);
|
||||||
|
|
||||||
// additional info about MAIN, PROG and JOIN
|
// additional info about MAIN, PROG and JOIN
|
||||||
bool main=TrackManager::getMainPower()==POWERMODE::ON;
|
bool main=TrackManager::getMainPower()==POWERMODE::ON;
|
||||||
bool prog=TrackManager::getProgPower()==POWERMODE::ON;
|
bool prog=TrackManager::getProgPower()==POWERMODE::ON;
|
||||||
@ -288,7 +291,7 @@ void CommandDistributor::broadcastPower() {
|
|||||||
const FSH * reason=F("");
|
const FSH * reason=F("");
|
||||||
if (join) {
|
if (join) {
|
||||||
reason = F(" JOIN"); // with space at start so we can append without space
|
reason = F(" JOIN"); // with space at start so we can append without space
|
||||||
broadcastReply(COMMAND_TYPE, F("<p1 %S>\n"),reason);
|
broadcastReply(COMMAND_TYPE, F("<p1%S>\n"),reason);
|
||||||
} else {
|
} else {
|
||||||
if (main) {
|
if (main) {
|
||||||
//reason = F("MAIN");
|
//reason = F("MAIN");
|
||||||
@ -299,9 +302,6 @@ void CommandDistributor::broadcastPower() {
|
|||||||
broadcastReply(COMMAND_TYPE, F("<p1 PROG>\n"));
|
broadcastReply(COMMAND_TYPE, F("<p1 PROG>\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state != '2')
|
|
||||||
broadcastReply(COMMAND_TYPE, F("<p%c>\n"),state);
|
|
||||||
#ifdef CD_HANDLE_RING
|
#ifdef CD_HANDLE_RING
|
||||||
// send '1' if all main are on, otherwise global state (which in that case is '0' or '2')
|
// send '1' if all main are on, otherwise global state (which in that case is '0' or '2')
|
||||||
broadcastReply(WITHROTTLE_TYPE, F("PPA%c\n"), main?'1': state);
|
broadcastReply(WITHROTTLE_TYPE, F("PPA%c\n"), main?'1': state);
|
||||||
|
@ -270,15 +270,19 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream *ringStream) {
|
|||||||
// This function can get stings of the form "<C OMM AND>" or "C OMM AND>"
|
// This function can get stings of the form "<C OMM AND>" or "C OMM AND>"
|
||||||
// found is true first after the leading "<" has been passed which results
|
// found is true first after the leading "<" has been passed which results
|
||||||
// in parseOne() getting c="C OMM AND>"
|
// in parseOne() getting c="C OMM AND>"
|
||||||
|
byte *cForLater = NULL;
|
||||||
bool found = (com[0] != '<');
|
bool found = (com[0] != '<');
|
||||||
for (byte *c=com; c[0] != '\0'; c++) {
|
for (byte *c=com; c[0] != '\0'; c++) {
|
||||||
if (found) {
|
if (found) {
|
||||||
parseOne(stream, c, ringStream);
|
cForLater = c;
|
||||||
found=false;
|
found=false;
|
||||||
}
|
}
|
||||||
if (c[0] == '<')
|
if (c[0] == '<') {
|
||||||
|
if (cForLater) parseOne(stream, cForLater, ringStream);
|
||||||
found = true;
|
found = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (cForLater) parseOne(stream, cForLater, ringStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||||
|
@ -78,11 +78,17 @@ int DCCTimer::freeMemory() {
|
|||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
|
||||||
|
#if __has_include("esp_idf_version.h")
|
||||||
#include "esp_idf_version.h"
|
#include "esp_idf_version.h"
|
||||||
#if ESP_IDF_VERSION_MAJOR > 4
|
#endif
|
||||||
|
#if ESP_IDF_VERSION_MAJOR == 4
|
||||||
|
// all well correct IDF version
|
||||||
|
#else
|
||||||
#error "DCC-EX does not support compiling with IDF version 5.0 or later. Downgrade your ESP32 library to a version that contains IDF version 4. Arduino ESP32 library 3.0.0 is too new. Downgrade to one of 2.0.9 to 2.0.17"
|
#error "DCC-EX does not support compiling with IDF version 5.0 or later. Downgrade your ESP32 library to a version that contains IDF version 4. Arduino ESP32 library 3.0.0 is too new. Downgrade to one of 2.0.9 to 2.0.17"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// protect all the rest of the code from IDF version 5
|
||||||
|
#if ESP_IDF_VERSION_MAJOR == 4
|
||||||
#include "DIAG.h"
|
#include "DIAG.h"
|
||||||
#include <driver/adc.h>
|
#include <driver/adc.h>
|
||||||
#include <soc/sens_reg.h>
|
#include <soc/sens_reg.h>
|
||||||
@ -322,5 +328,5 @@ void ADCee::scan() {
|
|||||||
|
|
||||||
void ADCee::begin() {
|
void ADCee::begin() {
|
||||||
}
|
}
|
||||||
|
#endif //IDF v4
|
||||||
#endif //ESP32
|
#endif //ESP32
|
||||||
|
@ -931,8 +931,9 @@ void RMFT2::loop2() {
|
|||||||
|
|
||||||
#ifndef DISABLE_PROG
|
#ifndef DISABLE_PROG
|
||||||
case OPCODE_JOIN:
|
case OPCODE_JOIN:
|
||||||
TrackManager::setPower(POWERMODE::ON);
|
|
||||||
TrackManager::setJoin(true);
|
TrackManager::setJoin(true);
|
||||||
|
TrackManager::setMainPower(POWERMODE::ON);
|
||||||
|
TrackManager::setProgPower(POWERMODE::ON);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPCODE_UNJOIN:
|
case OPCODE_UNJOIN:
|
||||||
|
BIN
Release_Notes/DCC-EX v5.4 Release Notes.xlsx
Normal file
BIN
Release_Notes/DCC-EX v5.4 Release Notes.xlsx
Normal file
Binary file not shown.
@ -668,7 +668,8 @@ void TrackManager::setJoin(bool joined) {
|
|||||||
if (track[t]->getMode() & TRACK_MODE_PROG) { // find PROG track
|
if (track[t]->getMode() & TRACK_MODE_PROG) { // find PROG track
|
||||||
tempProgTrack = t; // remember PROG track
|
tempProgTrack = t; // remember PROG track
|
||||||
setTrackMode(t, TRACK_MODE_MAIN);
|
setTrackMode(t, TRACK_MODE_MAIN);
|
||||||
track[t]->setPower(POWERMODE::ON); // if joined, always on
|
// setPower() of the track called after
|
||||||
|
// seperately after setJoin() instead
|
||||||
break; // there is only one prog track, done
|
break; // there is only one prog track, done
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -680,8 +681,6 @@ void TrackManager::setJoin(bool joined) {
|
|||||||
setTrackMode(tempProgTrack, TRACK_MODE_PROG); // set track mode back to prog
|
setTrackMode(tempProgTrack, TRACK_MODE_PROG); // set track mode back to prog
|
||||||
track[tempProgTrack]->setPower(tPTmode); // set power status as it was before
|
track[tempProgTrack]->setPower(tPTmode); // set power status as it was before
|
||||||
tempProgTrack = MAX_TRACKS+1;
|
tempProgTrack = MAX_TRACKS+1;
|
||||||
} else {
|
|
||||||
DIAG(F("Unjoin but no remembered prog track"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -500,9 +500,9 @@ void WiThrottle::getLocoCallback(int16_t locoid) {
|
|||||||
char addcmd[20]={'M',stashThrottleChar,'+', addrchar};
|
char addcmd[20]={'M',stashThrottleChar,'+', addrchar};
|
||||||
itoa(locoid,addcmd+4,10);
|
itoa(locoid,addcmd+4,10);
|
||||||
stashInstance->multithrottle(stashStream, (byte *)addcmd);
|
stashInstance->multithrottle(stashStream, (byte *)addcmd);
|
||||||
|
TrackManager::setJoin(true); // <1 JOIN> so we can drive loco away
|
||||||
TrackManager::setMainPower(POWERMODE::ON);
|
TrackManager::setMainPower(POWERMODE::ON);
|
||||||
TrackManager::setProgPower(POWERMODE::ON);
|
TrackManager::setProgPower(POWERMODE::ON);
|
||||||
TrackManager::setJoin(true); // <1 JOIN> so we can drive loco away
|
|
||||||
DIAG(F("LocoCallback commit success"));
|
DIAG(F("LocoCallback commit success"));
|
||||||
stashStream->commit();
|
stashStream->commit();
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,10 @@
|
|||||||
|
|
||||||
#include "StringFormatter.h"
|
#include "StringFormatter.h"
|
||||||
|
|
||||||
#define VERSION "5.4.4"
|
#define VERSION "5.4.6"
|
||||||
|
// 5.4.6 - Bugfix: Do not drop further commands in same packet
|
||||||
|
// 5.4.5 - ESP32: Better detection of correct IDF version
|
||||||
|
// - track power is always turned on after setJoin() not by setJoin()
|
||||||
// 5.4.4 - bugfix in parser, input buffer overrun and trailing > that did break <+>
|
// 5.4.4 - bugfix in parser, input buffer overrun and trailing > that did break <+>
|
||||||
// 5.4.3 - bugfix changeFn for functions 29..31
|
// 5.4.3 - bugfix changeFn for functions 29..31
|
||||||
// 5.4.2 - Reversed turnout bugfix
|
// 5.4.2 - Reversed turnout bugfix
|
||||||
|
8
wokwi/esp32/diagram.json
Normal file
8
wokwi/esp32/diagram.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"author": "Olivier Chatelain",
|
||||||
|
"editor": "wokwi",
|
||||||
|
"parts": [ { "type": "board-esp32-devkit-c-v4", "id": "esp", "top": 0, "left": 0, "attrs": {} } ],
|
||||||
|
"connections": [ [ "esp:TX", "$serialMonitor:RX", "", [] ], [ "esp:RX", "$serialMonitor:TX", "", [] ] ],
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
4
wokwi/esp32/wokwi.toml
Normal file
4
wokwi/esp32/wokwi.toml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[wokwi]
|
||||||
|
version = 1
|
||||||
|
firmware = '../../.pio/build/ESP32/firmware.bin'
|
||||||
|
elf = '../../.pio/build/ESP32/firmware.elf'
|
47
wokwi/mega/diagram.json
Normal file
47
wokwi/mega/diagram.json
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"author": "Olivier Chatelain",
|
||||||
|
"editor": "wokwi",
|
||||||
|
"parts": [
|
||||||
|
{ "type": "wokwi-arduino-mega", "id": "mega", "top": -249, "left": -147.6, "attrs": {} },
|
||||||
|
{ "type": "wokwi-logic-analyzer", "id": "logic1", "top": -374.05, "left": 355.2, "attrs": {} },
|
||||||
|
{
|
||||||
|
"type": "board-ssd1306",
|
||||||
|
"id": "oled1",
|
||||||
|
"top": -409.66,
|
||||||
|
"left": 57.83,
|
||||||
|
"attrs": { "i2cAddress": "0x3c" }
|
||||||
|
},
|
||||||
|
{ "type": "wokwi-gnd", "id": "gnd1", "top": -268.8, "left": 335.4, "attrs": {} },
|
||||||
|
{ "type": "wokwi-gnd", "id": "gnd2", "top": -57.6, "left": 239.4, "attrs": {} },
|
||||||
|
{
|
||||||
|
"type": "wokwi-resistor",
|
||||||
|
"id": "r1",
|
||||||
|
"top": -476.6,
|
||||||
|
"left": 152.75,
|
||||||
|
"rotate": 270,
|
||||||
|
"attrs": { "value": "1000" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "wokwi-resistor",
|
||||||
|
"id": "r2",
|
||||||
|
"top": -476.6,
|
||||||
|
"left": 75.95,
|
||||||
|
"rotate": 270,
|
||||||
|
"attrs": { "value": "1000" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
[ "mega:GND.1", "oled1:GND", "black", [ "v0" ] ],
|
||||||
|
[ "mega:5V", "oled1:VCC", "red", [ "v-348.3", "h88.55" ] ],
|
||||||
|
[ "gnd1:GND", "logic1:GND", "black", [ "v0" ] ],
|
||||||
|
[ "mega:GND.5", "gnd2:GND", "black", [ "v0" ] ],
|
||||||
|
[ "oled1:SCL", "r2:1", "green", [ "v0" ] ],
|
||||||
|
[ "oled1:SDA", "r1:1", "green", [ "v0" ] ],
|
||||||
|
[ "r2:2", "oled1:VCC", "green", [ "h38.4", "v87.6", "h-38.4" ] ],
|
||||||
|
[ "r2:2", "r1:2", "green", [ "h0" ] ],
|
||||||
|
[ "mega:SCL", "oled1:SCL", "green", [ "v-144", "h172.5" ] ],
|
||||||
|
[ "mega:SDA", "oled1:SDA", "green", [ "v-134.4", "h162.8" ] ]
|
||||||
|
],
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
4
wokwi/mega/wokwi.toml
Normal file
4
wokwi/mega/wokwi.toml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[wokwi]
|
||||||
|
version = 1
|
||||||
|
firmware = '../../.pio/build/mega2560/firmware.hex'
|
||||||
|
elf = '../../.pio/build/mega2560/firmware.elf'
|
8
wokwi/nano/diagram.json
Normal file
8
wokwi/nano/diagram.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"author": "Olivier Chatelain",
|
||||||
|
"editor": "wokwi",
|
||||||
|
"parts": [ { "type": "wokwi-arduino-nano", "id": "nano", "top": 0, "left": 0, "attrs": {} } ],
|
||||||
|
"connections": [],
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
4
wokwi/nano/wokwi.toml
Normal file
4
wokwi/nano/wokwi.toml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[wokwi]
|
||||||
|
version = 1
|
||||||
|
firmware = '../../.pio/build/nano/firmware.hex'
|
||||||
|
elf = '../../.pio/build/nano/firmware.elf'
|
8
wokwi/uno/diagram.json
Normal file
8
wokwi/uno/diagram.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"author": "Olivier Chatelain",
|
||||||
|
"editor": "wokwi",
|
||||||
|
"parts": [ { "type": "wokwi-arduino-uno", "id": "uno", "top": 0, "left": 0, "attrs": {} } ],
|
||||||
|
"connections": [],
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
4
wokwi/uno/wokwi.toml
Normal file
4
wokwi/uno/wokwi.toml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[wokwi]
|
||||||
|
version = 1
|
||||||
|
firmware = '../../.pio/build/uno/firmware.hex'
|
||||||
|
elf = '../../.pio/build/uno/firmware.elf'
|
Loading…
x
Reference in New Issue
Block a user