mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-02-18 23:16:03 +01:00
Add CMRI work-arounds for ArduinoCMRI library
Work-arounds enabled by "#define ARDUINOCMRI_COMPATIBLE TRUE" in config.h
This commit is contained in:
parent
0154ab7631
commit
bbc4339b69
39
IO_CMRI.cpp
39
IO_CMRI.cpp
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "IO_CMRI.h"
|
#include "IO_CMRI.h"
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* CMRIbus implementation
|
* CMRIbus implementation
|
||||||
@ -36,12 +37,18 @@ CMRIbus::CMRIbus(uint8_t busNo, HardwareSerial &serial, unsigned long baud, uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Max message length is 256+6=262 bytes.
|
// Max message length is 256+6=262 bytes.
|
||||||
// Each byte is one start bit, 8 data bits and 1 stop bit = 10 bits per byte.
|
// Each byte is one start bit, 8 data bits and 1 or 2 stop bits, assume 11 bits per byte.
|
||||||
// Calculate timeout based on double this time.
|
// Calculate timeout based on treble this time.
|
||||||
_timeoutPeriod = 2 * 10 * 262 * 1000UL / (_baud / 1000UL);
|
_timeoutPeriod = 3 * 11 * 262 * 1000UL / (_baud / 1000UL);
|
||||||
|
#if ARDUINOCMRI_COMPATIBLE
|
||||||
// Calculate the time in microseconds to transmit one byte (10 bits).
|
// NOTE: The ArduinoCMRI library, unless modified, contains a 'delay(50)' between
|
||||||
_byteTransmitTime = 1000000UL * 10 / _baud;
|
// receiving the end of the prompt message and starting to send the response. This
|
||||||
|
// is allowed for below.
|
||||||
|
_timeoutPeriod += 50000UL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Calculate the time in microseconds to transmit one byte (11 bits max).
|
||||||
|
_byteTransmitTime = 1000000UL * 11 / _baud;
|
||||||
// Postdelay is only required if we need to allow for data still being sent when
|
// Postdelay is only required if we need to allow for data still being sent when
|
||||||
// we want to switch off the transmitter. The flush() method of HardwareSerial
|
// we want to switch off the transmitter. The flush() method of HardwareSerial
|
||||||
// ensures that the data has completed being sent over the line.
|
// ensures that the data has completed being sent over the line.
|
||||||
@ -148,9 +155,9 @@ void CMRIbus::processOutgoing() {
|
|||||||
case TD_TRANSMIT:
|
case TD_TRANSMIT:
|
||||||
charsSent = sendData(_currentNode);
|
charsSent = sendData(_currentNode);
|
||||||
_transmitState = TD_PROMPT;
|
_transmitState = TD_PROMPT;
|
||||||
// Defer next entry for as long as it takes to transmit the characters,
|
// Defer next entry for as long as it takes to transmit the characters,
|
||||||
// to allow output queue to empty.
|
// to allow output queue to empty. Allow 2 bytes extra.
|
||||||
delayUntil(_currentMicros+_byteTransmitTime*charsSent);
|
delayUntil(_currentMicros+_byteTransmitTime*(charsSent+2));
|
||||||
break;
|
break;
|
||||||
case TD_PROMPT:
|
case TD_PROMPT:
|
||||||
charsSent = requestData(_currentNode);
|
charsSent = requestData(_currentNode);
|
||||||
@ -184,7 +191,7 @@ void CMRIbus::processIncoming() {
|
|||||||
if (data == SYN) nextState = RD_SYN2;
|
if (data == SYN) nextState = RD_SYN2;
|
||||||
break;
|
break;
|
||||||
case RD_SYN2:
|
case RD_SYN2:
|
||||||
if (data == SYN) nextState = RD_STX;
|
if (data == SYN) nextState = RD_STX; else nextState = RD_SYN2;
|
||||||
break;
|
break;
|
||||||
case RD_STX:
|
case RD_STX:
|
||||||
if (data == STX) nextState = RD_ADDR;
|
if (data == STX) nextState = RD_ADDR;
|
||||||
@ -225,9 +232,17 @@ void CMRIbus::processIncoming() {
|
|||||||
void CMRIbus::enableTransmitter() {
|
void CMRIbus::enableTransmitter() {
|
||||||
if (_transmitEnablePin != VPIN_NONE)
|
if (_transmitEnablePin != VPIN_NONE)
|
||||||
ArduinoPins::fastWriteDigital(_transmitEnablePin, 1);
|
ArduinoPins::fastWriteDigital(_transmitEnablePin, 1);
|
||||||
// Send an extra SYN character to ensure transmitter and
|
// If we need a delay before we start the packet header,
|
||||||
// remote receiver have stabilised before we start the packet.
|
// we can send a character or two to synchronise the
|
||||||
|
// transmitter and receiver.
|
||||||
|
// SYN characters should be used, but a bug in the
|
||||||
|
// ArduinoCMRI library causes it to ignore the packet if
|
||||||
|
// it's preceded by an odd number of SYN characters.
|
||||||
|
// So send a SYN followed by a NUL in that case.
|
||||||
_serial->write(SYN);
|
_serial->write(SYN);
|
||||||
|
#if ARDUINOCMRI_COMPATIBLE
|
||||||
|
_serial->write(NUL); // Reset the ArduinoCMRI library's parser
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// If configured for half duplex RS485, switch RS485 interface
|
// If configured for half duplex RS485, switch RS485 interface
|
||||||
|
18
IO_CMRI.h
18
IO_CMRI.h
@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* CMRIbus
|
||||||
|
* =======
|
||||||
* To define a CMRI bus, example syntax:
|
* To define a CMRI bus, example syntax:
|
||||||
* CMRIbus::create(bus, serial, baud[, cycletime[, pin]]);
|
* CMRIbus::create(bus, serial, baud[, cycletime[, pin]]);
|
||||||
*
|
*
|
||||||
@ -29,6 +31,15 @@
|
|||||||
*
|
*
|
||||||
* Each bus must use a different serial port.
|
* Each bus must use a different serial port.
|
||||||
*
|
*
|
||||||
|
* IMPORTANT: If you are using ArduinoCMRI library code by Michael Adams, at the time of writing this library
|
||||||
|
* is not compliant with the LCS-9.10.1 specification for CMRInet protocol.
|
||||||
|
* Various work-arounds may be enabled within the driver by adding the following line to your config.h file,
|
||||||
|
* to allow nodes running the ArduinoCMRI library to communicate:
|
||||||
|
*
|
||||||
|
* #define ARDUINOCMRI_COMPATIBLE TRUE
|
||||||
|
*
|
||||||
|
* CMRINode
|
||||||
|
* ========
|
||||||
* To define a CMRI node and associate it with a CMRI bus,
|
* To define a CMRI node and associate it with a CMRI bus,
|
||||||
* CMRInode::create(firstVPIN, numVPINs, bus, address, type [, inputs, outputs]);
|
* CMRInode::create(firstVPIN, numVPINs, bus, address, type [, inputs, outputs]);
|
||||||
*
|
*
|
||||||
@ -196,6 +207,7 @@ private:
|
|||||||
|
|
||||||
// Definition of special characters in CMRInet protocol
|
// Definition of special characters in CMRInet protocol
|
||||||
enum : uint8_t {
|
enum : uint8_t {
|
||||||
|
NUL = 0x00,
|
||||||
STX = 0x02,
|
STX = 0x02,
|
||||||
ETX = 0x03,
|
ETX = 0x03,
|
||||||
DLE = 0x10,
|
DLE = 0x10,
|
||||||
@ -209,8 +221,12 @@ public:
|
|||||||
|
|
||||||
// Device-specific initialisation
|
// Device-specific initialisation
|
||||||
void _begin() override {
|
void _begin() override {
|
||||||
// Some sources quote one stop bit, some two.
|
// CMRInet spec states one stop bit, JMRI and ArduinoCMRI use two stop bits
|
||||||
|
#if ARDUINOCMRI_COMPATIBLE
|
||||||
|
_serial->begin(_baud, SERIAL_8N2);
|
||||||
|
#else
|
||||||
_serial->begin(_baud, SERIAL_8N1);
|
_serial->begin(_baud, SERIAL_8N1);
|
||||||
|
#endif
|
||||||
#if defined(DIAG_IO)
|
#if defined(DIAG_IO)
|
||||||
_display();
|
_display();
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user