mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-24 00:26:13 +01:00
Compare commits
4 Commits
a99388930c
...
5ee13bdbab
Author | SHA1 | Date | |
---|---|---|---|
|
5ee13bdbab | ||
|
3b162996ad | ||
|
fb414a7a50 | ||
|
53f598192c |
83
.github/workflows/main.yml
vendored
83
.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:
|
||||||
|
path: |
|
||||||
|
~/.cache/pip
|
||||||
|
~/.platformio/.cache
|
||||||
|
key: ${{ runner.os }}-pio
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.9'
|
||||||
- name: Install PlatformIO Core
|
- name: Install PlatformIO Core
|
||||||
run: pip install -U platformio
|
run: pip install --upgrade platformio
|
||||||
- name: Copy generic config over
|
|
||||||
run: cp config.example.h config.h
|
- name: Use sample "config.example.h" for compilations
|
||||||
- name: Compile Command Station (AVR)
|
run: mv $GITHUB_WORKSPACE/config.example.h $GITHUB_WORKSPACE/config.h
|
||||||
run: python -m platformio run
|
|
||||||
|
- 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
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* © 2022, Peter Cole. All rights reserved.
|
* © 2022, Peter Cole. All rights reserved.
|
||||||
|
* © 2024, Harald Barth. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of EX-CommandStation
|
* This file is part of EX-CommandStation
|
||||||
*
|
*
|
||||||
|
@ -98,13 +99,22 @@ private:
|
||||||
_numAnaloguePins = receiveBuffer[2];
|
_numAnaloguePins = receiveBuffer[2];
|
||||||
|
|
||||||
// See if we already have suitable buffers assigned
|
// See if we already have suitable buffers assigned
|
||||||
|
if (_numDigitalPins>0) {
|
||||||
size_t digitalBytesNeeded = (_numDigitalPins + 7) / 8;
|
size_t digitalBytesNeeded = (_numDigitalPins + 7) / 8;
|
||||||
if (_digitalPinBytes < digitalBytesNeeded) {
|
if (_digitalPinBytes < digitalBytesNeeded) {
|
||||||
// Not enough space, free any existing buffer and allocate a new one
|
// Not enough space, free any existing buffer and allocate a new one
|
||||||
if (_digitalPinBytes > 0) free(_digitalInputStates);
|
if (_digitalPinBytes > 0) free(_digitalInputStates);
|
||||||
_digitalInputStates = (byte*) calloc(_digitalPinBytes, 1);
|
if ((_digitalInputStates = (byte*) calloc(digitalBytesNeeded, 1)) != NULL) {
|
||||||
_digitalPinBytes = digitalBytesNeeded;
|
_digitalPinBytes = digitalBytesNeeded;
|
||||||
|
} else {
|
||||||
|
DIAG(F("EX-IOExpander I2C:%s ERROR alloc %d bytes"), _I2CAddress.toString(), digitalBytesNeeded);
|
||||||
|
_deviceState = DEVSTATE_FAILED;
|
||||||
|
_digitalPinBytes = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_numAnaloguePins>0) {
|
||||||
size_t analogueBytesNeeded = _numAnaloguePins * 2;
|
size_t analogueBytesNeeded = _numAnaloguePins * 2;
|
||||||
if (_analoguePinBytes < analogueBytesNeeded) {
|
if (_analoguePinBytes < analogueBytesNeeded) {
|
||||||
// Free any existing buffers and allocate new ones.
|
// Free any existing buffers and allocate new ones.
|
||||||
|
@ -116,7 +126,17 @@ private:
|
||||||
_analogueInputStates = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
_analogueInputStates = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
||||||
_analogueInputBuffer = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
_analogueInputBuffer = (uint8_t*) calloc(analogueBytesNeeded, 1);
|
||||||
_analoguePinMap = (uint8_t*) calloc(_numAnaloguePins, 1);
|
_analoguePinMap = (uint8_t*) calloc(_numAnaloguePins, 1);
|
||||||
|
if (_analogueInputStates != NULL &&
|
||||||
|
_analogueInputBuffer != NULL &&
|
||||||
|
_analoguePinMap != NULL) {
|
||||||
_analoguePinBytes = analogueBytesNeeded;
|
_analoguePinBytes = analogueBytesNeeded;
|
||||||
|
} else {
|
||||||
|
DIAG(F("EX-IOExpander I2C:%s ERROR alloc analog pin bytes"), _I2CAddress.toString());
|
||||||
|
_deviceState = DEVSTATE_FAILED;
|
||||||
|
_analoguePinBytes = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DIAG(F("EX-IOExpander I2C:%s ERROR configuring device"), _I2CAddress.toString());
|
DIAG(F("EX-IOExpander I2C:%s ERROR configuring device"), _I2CAddress.toString());
|
||||||
|
@ -124,8 +144,8 @@ private:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We now need to retrieve the analogue pin map
|
// We now need to retrieve the analogue pin map if there are analogue pins
|
||||||
if (status == I2C_STATUS_OK) {
|
if (status == I2C_STATUS_OK && _numAnaloguePins>0) {
|
||||||
commandBuffer[0] = EXIOINITA;
|
commandBuffer[0] = EXIOINITA;
|
||||||
status = I2CManager.read(_I2CAddress, _analoguePinMap, _numAnaloguePins, commandBuffer, 1);
|
status = I2CManager.read(_I2CAddress, _analoguePinMap, _numAnaloguePins, commandBuffer, 1);
|
||||||
}
|
}
|
||||||
|
@ -239,7 +259,7 @@ private:
|
||||||
|
|
||||||
// If we're not doing anything now, check to see if a new input transfer is due.
|
// If we're not doing anything now, check to see if a new input transfer is due.
|
||||||
if (_readState == RDS_IDLE) {
|
if (_readState == RDS_IDLE) {
|
||||||
if (currentMicros - _lastDigitalRead > _digitalRefresh) { // Delay for digital read refresh
|
if (_numDigitalPins>0 && currentMicros - _lastDigitalRead > _digitalRefresh) { // Delay for digital read refresh
|
||||||
// Issue new read request for digital states. As the request is non-blocking, the buffer has to
|
// Issue new read request for digital states. As the request is non-blocking, the buffer has to
|
||||||
// be allocated from heap (object state).
|
// be allocated from heap (object state).
|
||||||
_readCommandBuffer[0] = EXIORDD;
|
_readCommandBuffer[0] = EXIORDD;
|
||||||
|
@ -247,7 +267,7 @@ private:
|
||||||
// non-blocking read
|
// non-blocking read
|
||||||
_lastDigitalRead = currentMicros;
|
_lastDigitalRead = currentMicros;
|
||||||
_readState = RDS_DIGITAL;
|
_readState = RDS_DIGITAL;
|
||||||
} else if (currentMicros - _lastAnalogueRead > _analogueRefresh) { // Delay for analogue read refresh
|
} else if (_numAnaloguePins>0 && currentMicros - _lastAnalogueRead > _analogueRefresh) { // Delay for analogue read refresh
|
||||||
// Issue new read for analogue input states
|
// Issue new read for analogue input states
|
||||||
_readCommandBuffer[0] = EXIORDAN;
|
_readCommandBuffer[0] = EXIORDAN;
|
||||||
I2CManager.read(_I2CAddress, _analogueInputBuffer,
|
I2CManager.read(_I2CAddress, _analogueInputBuffer,
|
||||||
|
@ -362,14 +382,14 @@ private:
|
||||||
uint8_t _minorVer = 0;
|
uint8_t _minorVer = 0;
|
||||||
uint8_t _patchVer = 0;
|
uint8_t _patchVer = 0;
|
||||||
|
|
||||||
uint8_t* _digitalInputStates;
|
uint8_t* _digitalInputStates = NULL;
|
||||||
uint8_t* _analogueInputStates;
|
uint8_t* _analogueInputStates = NULL;
|
||||||
uint8_t* _analogueInputBuffer; // buffer for I2C input transfers
|
uint8_t* _analogueInputBuffer = NULL; // buffer for I2C input transfers
|
||||||
uint8_t _readCommandBuffer[1];
|
uint8_t _readCommandBuffer[1];
|
||||||
|
|
||||||
uint8_t _digitalPinBytes = 0; // Size of allocated memory buffer (may be longer than needed)
|
uint8_t _digitalPinBytes = 0; // Size of allocated memory buffer (may be longer than needed)
|
||||||
uint8_t _analoguePinBytes = 0; // Size of allocated memory buffers (may be longer than needed)
|
uint8_t _analoguePinBytes = 0; // Size of allocated memory buffer (may be longer than needed)
|
||||||
uint8_t* _analoguePinMap;
|
uint8_t* _analoguePinMap = NULL;
|
||||||
I2CRB _i2crb;
|
I2CRB _i2crb;
|
||||||
|
|
||||||
enum {RDS_IDLE, RDS_DIGITAL, RDS_ANALOGUE}; // Read operation states
|
enum {RDS_IDLE, RDS_DIGITAL, RDS_ANALOGUE}; // Read operation states
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
#include "StringFormatter.h"
|
#include "StringFormatter.h"
|
||||||
|
|
||||||
#define VERSION "5.0.8"
|
#define VERSION "5.0.9"
|
||||||
|
// 5.0.9 - EX-IOExpander bug fix for memory allocation
|
||||||
|
// - EX-IOExpander bug fix to allow for devices with no analogue or no digital pins
|
||||||
// 5.0.8 - Bugfix: Do not crash on turnouts without description
|
// 5.0.8 - Bugfix: Do not crash on turnouts without description
|
||||||
// 5.0.7 - Only flag 2.2.0.0-dev as broken, not 2.2.0.0
|
// 5.0.7 - Only flag 2.2.0.0-dev as broken, not 2.2.0.0
|
||||||
// 5.0.6 - Bugfix lost TURNOUTL description
|
// 5.0.6 - Bugfix lost TURNOUTL description
|
||||||
|
|
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…
Reference in New Issue
Block a user