1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-22 23:56:13 +01:00
This commit is contained in:
Neil McKechnie 2023-03-15 09:21:24 +00:00
commit 72c76391a5
9 changed files with 114 additions and 84 deletions

7
.gitignore vendored
View File

@ -7,16 +7,9 @@ Release/*
.pio/
.vscode/
config.h
.vscode/*
# mySetup.h
mySetup.cpp
myHal.cpp
# myAutomation.h
myFilter.cpp
# myAutomation.h
# myLayout.h
my*.h
!my*.example.h
.vscode/extensions.json
.vscode/extensions.json
compile_commands.json

View File

@ -1,10 +0,0 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

12
.vscode/settings.json vendored
View File

@ -1,12 +0,0 @@
{
"files.associations": {
"array": "cpp",
"deque": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"string_view": "cpp",
"initializer_list": "cpp",
"cstdint": "cpp"
}
}

View File

@ -1,5 +1,6 @@
/*
* © 2021, Chris Harlow, Neil McKechnie. All rights reserved.
* © 2023, Harald Barth.
*
* This file is part of CommandStation-EX
*
@ -52,7 +53,7 @@ Display::Display(DisplayDevice *deviceDriver) {
_deviceDriver = deviceDriver;
// Get device dimensions in characters (e.g. 16x2).
numCharacterColumns = _deviceDriver->getNumCols();
numCharacterRows = _deviceDriver->getNumRows();;
numCharacterRows = _deviceDriver->getNumRows();
for (uint8_t row = 0; row < MAX_CHARACTER_ROWS; row++)
rowBuffer[row][0] = '\0';
topRow = ROW_INITIAL; // loop2 will fill from row 0
@ -173,16 +174,18 @@ bool Display::findNextNonBlankRow() {
rowNext = 0;
else
rowNext = rowNext + 1;
if (rowNext >= MAX_CHARACTER_ROWS) rowNext = ROW_INITIAL;
#if SCROLLMODE == 1
if (rowNext >= MAX_CHARACTER_ROWS) {
// Finished if we've looped back to start
if (rowNext == ROW_INITIAL) {
rowNext = ROW_INITIAL;
noMoreRowsToDisplay = true;
return false;
}
#else
// Finished if we're back to the first one shown
if (rowNext >= MAX_CHARACTER_ROWS)
rowNext = 0;
if (rowNext == rowFirst) {
// Finished if we're back to the first one shown
noMoreRowsToDisplay = true;
return false;
}

View File

@ -105,13 +105,10 @@ uint16_t RMFT2::getOperand(byte n) {
// getOperand static version, must be provided prog counter from loop etc.
uint16_t RMFT2::getOperand(int progCounter,byte n) {
int offset=progCounter+1+(n*3);
if (offset&1) {
byte lsb=GETHIGHFLASH(RouteCode,offset);
byte msb=GETHIGHFLASH(RouteCode,offset+1);
return msb<<8|lsb;
}
return GETHIGHFLASHW(RouteCode,offset);
}
LookList::LookList(int16_t size) {
m_size=size;

View File

@ -1 +1 @@
#define GITHUB_SHA "devel-202303101548Z"
#define GITHUB_SHA "devel-202303141949Z"

View File

@ -154,12 +154,30 @@ private:
// Main loop, collect both digital and analogue pin states continuously (faster sensor/input reads)
void _loop(unsigned long currentMicros) override {
(void)currentMicros; // remove warning
if (_deviceState == DEVSTATE_FAILED) return;
if (_deviceState == DEVSTATE_FAILED) return; // If device failed, return
uint8_t status = _i2crb.status;
if (status == I2C_STATUS_PENDING) return; // If device busy, return
if (status == I2C_STATUS_OK) { // If device ok, read input data
if (_commandFlag) {
if (currentMicros - _lastDigitalRead > _digitalRefresh) { // Delay for digital read refresh
_lastDigitalRead = currentMicros;
_command1Buffer[0] = EXIORDD;
I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _command1Buffer, 1, &_i2crb);
}
} else {
if (currentMicros - _lastAnalogueRead > _analogueRefresh) { // Delay for analogue read refresh
_lastAnalogueRead = currentMicros;
_command1Buffer[0] = EXIORDAN;
I2CManager.read(_i2cAddress, _analogueInputStates, _analoguePinBytes, _command1Buffer, 1, &_i2crb);
byte _tempAnalogue[_analoguePinBytes]; // Setup temp buffer so reads come from known state
I2CManager.read(_i2cAddress, _tempAnalogue, _analoguePinBytes, _command1Buffer, 1, &_i2crb);
memcpy(_analogueInputStates, _tempAnalogue, _analoguePinBytes); // Copy temp buffer to states
}
}
_commandFlag = !_commandFlag;
} else {
DIAG(F("EX-IOExpander I2C:%s Error:%d %S"), _I2CAddress.toString(), status, I2CManager.getErrorMessage(status));
_deviceState = DEVSTATE_FAILED;
}
}
// Obtain the correct analogue input value
@ -191,11 +209,16 @@ private:
_digitalOutBuffer[0] = EXIOWRD;
_digitalOutBuffer[1] = pin;
_digitalOutBuffer[2] = value;
I2CManager.read(_i2cAddress, _command1Buffer, 1, _digitalOutBuffer, 3, &_i2crb);
uint8_t status = I2CManager.read(_i2cAddress, _command1Buffer, 1, _digitalOutBuffer, 3);
if (status != I2C_STATUS_OK) {
DIAG(F("EX-IOExpander I2C:%s Error:%d %S"), _I2CAddress.toString(), status, I2CManager.getErrorMessage(status));
_deviceState = DEVSTATE_FAILED;
} else {
if (_command1Buffer[0] != EXIORDY) {
DIAG(F("Vpin %d cannot be used as a digital output pin"), (int)vpin);
}
}
}
void _writeAnalogue(VPIN vpin, int value, uint8_t profile, uint16_t duration) override {
if (_deviceState == DEVSTATE_FAILED) return;
@ -211,11 +234,16 @@ private:
_servoBuffer[4] = profile;
_servoBuffer[5] = duration & 0xFF;
_servoBuffer[6] = duration >> 8;
I2CManager.read(_i2cAddress, _command1Buffer, 1, _servoBuffer, 7, &_i2crb);
uint8_t status = I2CManager.read(_i2cAddress, _command1Buffer, 1, _servoBuffer, 7);
if (status != I2C_STATUS_OK) {
DIAG(F("EX-IOExpander I2C:%s Error:%d %S"), _I2CAddress.toString(), status, I2CManager.getErrorMessage(status));
_deviceState = DEVSTATE_FAILED;
} else {
if (_command1Buffer[0] != EXIORDY) {
DIAG(F("Vpin %d cannot be used as a servo/PWM pin"), (int)vpin);
}
}
}
void _display() override {
DIAG(F("EX-IOExpander I2C:%s v%d.%d.%d Vpins %d-%d %S"),
@ -243,6 +271,11 @@ private:
byte _servoBuffer[7];
uint8_t* _analoguePinMap;
I2CRB _i2crb;
bool _commandFlag = 1;
unsigned long _lastDigitalRead = 0;
unsigned long _lastAnalogueRead = 0;
const unsigned long _digitalRefresh = 10000UL; // Delay refreshing digital inputs for 10ms
const unsigned long _analogueRefresh = 50000UL; // Delay refreshing analogue inputs for 50ms
// EX-IOExpander protocol flags
enum {

View File

@ -4,24 +4,37 @@ General points:
- Commands below have a single character opcode and parameters.
Even <JA> is actually read as <J A>
- Keyword parameters are shown in upper case but may be entered in mixed case.
- value parameters are numeric.
- value parameters are decimal numeric (unless otherwise noted)
- [something] indicates its optional.
- Not all commands have a response, and not all responses come from the last commands that you have issued.
- Not all commands have a response, and broadcasts mean that not all responses come from the last commands that you have issued.
Startup status
<s>
<s> Return status like
<iDCC-EX V-4.2.22 / MEGA / STANDARD_MOTOR_SHIELD G-devel-202302281422Z>
also returns defined turnout list:
<H id 1|0> 1=thrown
Track power management
<1>
<1 MAIN|PROG|JOIN>
<0>
<0 MAIN|PROG>
Track power management. After power commands a power state is broadcast to all throttles.
<1> Power on all
<1 MAIN|PROG|JOIN> Power on MAIN or PROG track
<1 JOIN> Power on MAIN and PROG track but send main track data on both.
<0> Power off all tracks
<0 MAIN|PROG> Power off main or prog track
Basic manual loco control
<t locoid speed direction> Throttle loco.
speed in JMRI-form (-1=ESTOP, 0=STOP, 1..126 = DCC speeds 2..127)
direction 1=forward, 0=reverse
For response see broadcast <l>
<F locoid function 1|0> Set loco function 1=ON, 0-OFF
For response see broadcast <l>
<!> emergency stop all locos
<T id 0|1|T|C> Control turnout id, 0=C=Closed, 1=T=Thrown
response broadcast <H id 0|1>
Basic manual control
<t cab speed direction>
<F cab function 1|0>
<!>
<T id 0|1|T|C>
DCC accessory control
<a address subaddress activate [onoff]>
@ -35,25 +48,30 @@ Note: Turnouts are best defined in myAutomation.h where a turnout description ca
<T id VPIN vpin>
<T id DCC addr subaddr>
<T id DCC linearaddr>
Valid commands respond with <O>
Outputs (Used by JMRI, not required by EXRAIL)
<Z id vpin active> Define an output pin that JMRI can set by id
<Z id activate> Activate an output pin by id
Outputs
<Z id activate>
<Z id vpin iflag>
Sensors (Used by JMRI, not required by EXRAIL)
<S id vpin pullup> define a sensor to be monitored.
Responses <Q id> and <q id> as sensor changes
Sensors
<S id vpin pullup>
Decoder programming - main track
<w cab cv value> POM write value to cv on loco
<b cab cv bit value> POM write bit to cv on loco
Decoder programming
<w cab cv value>
<b cab cv bit value>
<W cabid>
<W cv value>
<V cv value>
<V cv bit value>
<R>
<R cv>
<B cv bit value>
Decoder Programming - prog track
<W cabid> Clear consist and write new cab id (includes long/short settings)
Responds <W cabid> or <W -1> for error
<W cv value> Write value to cv
<V cv predictedValue> Read cv value, much faster if prediction is correct.
<V cv bit predictedValue> Read CV bit
<R> Read drive-away loco id. (May be a consist id)
<D ACK ON|OFF>
<D ACK LIMIT|MIN|MAX|RETRY value>
<D PROGBOOST>
@ -152,6 +170,8 @@ Obsolete commands/formats
<B cv bit value obsolete obsolete>
<R cv obsolete obsolete>
<W cv value obsolete obsolete>
<R cv> V command is much faster if prediction is correct.
<B cv bit value> V command is much faster if prediction is correct.
Broadcast responses
Note: broadcasts are sent to all throttles when appropriate (usually because something has changed)

View File

@ -4,8 +4,14 @@
#include "StringFormatter.h"
#define VERSION "4.2.24"
// 4.3.24 - Bugfix Ethernet shield: Static IP now possible
#define VERSION "4.2.27"
// 4.2.27 - Bugfix LCD showed random characters in SCROLLMODE 2
// 4.2.26 - EX-IOExpander device driver enhancements
// - Enhance I2C error checking
// - Introduce delays to _loop to allow room for other I2C device comms
// - Improve analogue read reliability
// 4.2.25 - Bugfix SAMD21 Exrail odd byte boundary
// 4.2.24 - Bugfix Ethernet shield: Static IP now possible
// 4.2.23 - Bugfix signalpin2 was not set up in shadow port
// 4.2.22 - Implement broadcast of Track Manager changes
// 4.2.21 - Implement non-blocking I2C for EX-IOExpander device driver