1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-23 12:51:24 +01:00
This commit is contained in:
Asbelos 2024-10-23 14:11:36 +01:00
parent 68809fa8d5
commit a0a503ad7d
6 changed files with 76 additions and 1 deletions

19
DCC.cpp
View File

@ -389,6 +389,25 @@ void DCC::writeCVByteMain(int cab, int cv, byte bValue) {
DCCWaveform::mainTrack.schedulePacket(b, nB, 4);
}
//
// readCVByteMain: Read a byte with PoM on main.
// This requires Railcom active
//
void DCC::readCVByteMain(int cab, int cv, ACK_CALLBACK callback) {
byte b[5];
byte nB = 0;
if (cab > HIGHEST_SHORT_ADDR)
b[nB++] = highByte(cab) | 0xC0; // convert train number into a two-byte address
b[nB++] = lowByte(cab);
b[nB++] = cv1(READ_BYTE_MAIN, cv); // any CV>1023 will become modulus(1024) due to bit-mask of 0x03
b[nB++] = cv2(cv);
b[nB++] = 0;
DCCWaveform::mainTrack.schedulePacket(b, nB, 4);
Railcom::anticipate(cab,cv,callback);
}
//
// writeCVBitMain: Write a bit of a byte with PoM on main. This writes
// the 5 byte sized packet to implement this DCC function

3
DCC.h
View File

@ -64,6 +64,8 @@ public:
static uint8_t getThrottleFrequency(int cab);
static bool getThrottleDirection(int cab);
static void writeCVByteMain(int cab, int cv, byte bValue);
static void readCVByteMain(int cab, int cv, ACK_CALLBACK callback);
static void writeCVBitMain(int cab, int cv, byte bNum, bool bValue);
static void setFunction(int cab, byte fByte, byte eByte);
static bool setFn(int cab, int16_t functionNumber, bool on);
@ -128,6 +130,7 @@ private:
// NMRA codes #
static const byte SET_SPEED = 0x3f;
static const byte WRITE_BYTE_MAIN = 0xEC;
static const byte READ_BYTE_MAIN = 0xE4;
static const byte WRITE_BIT_MAIN = 0xE8;
static const byte WRITE_BYTE = 0x7C;
static const byte VERIFY_BYTE = 0x74;

View File

@ -480,6 +480,14 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
break;
DCC::writeCVByteMain(p[0], p[1], p[2]);
return;
case 'r': // READ CV on MAIN <r CAB CV> Requires Railcom
if (params != 2)
break;
if (!DCCWaveform::isRailcom()) break;
if (!stashCallback(stream, p, ringStream)) break;
DCC::readCVByteMain(p[0], p[1],callback_r);
return;
case 'b': // WRITE CV BIT ON MAIN <b CAB CV BIT VALUE>
if (params != 4)
@ -1417,6 +1425,12 @@ void DCCEXParser::callback_R(int16_t result)
commitAsyncReplyStream();
}
void DCCEXParser::callback_r(int16_t result)
{
StringFormatter::send(getAsyncReplyStream(), F("<r MAIN %d %d %d >\n"), stashP[0], stashP[1], result);
commitAsyncReplyStream();
}
void DCCEXParser::callback_Rloco(int16_t result) {
const FSH * detail;
if (result<=0) {

View File

@ -68,7 +68,8 @@ struct DCCEXParser
static void callback_W(int16_t result);
static void callback_W4(int16_t result);
static void callback_B(int16_t result);
static void callback_R(int16_t result);
static void callback_R(int16_t result); // prog
static void callback_r(int16_t result); // main
static void callback_Rloco(int16_t result);
static void callback_Wloco(int16_t result);
static void callback_Wconsist(int16_t result);

View File

@ -145,6 +145,10 @@ Railcom::Railcom(uint16_t blockvpin) {
lastChannel1Loco=0;
vpin=blockvpin;
}
uint16_t Railcom::expectLoco=0;
uint16_t Railcom::expectCV=0;
uint16_t Railcom::expectWait=0;
ACK_CALLBACK Railcom::expectCallback=0;
// Process is called by a raw data collector.
@ -170,6 +174,30 @@ void Railcom::process(uint8_t * inbound, uint8_t length) {
}
}
if (expectCV && DCCWaveform::getRailcomLastLocoAddress()==expectLoco) {
if (length>=4) {
auto v2=GETHIGHFLASH(decode,inbound[2]);
auto v3=GETHIGHFLASH(decode,inbound[3]);
uint16_t packet=(v2<<6) | (v3 & 0x3f);
// packet is 12 bits TTTTDDDDDDDD
byte type=(packet>>8) & 0x0F;
byte data= packet & 0xFF;
if (type==RMOB_POM) {
DIAG(F("POM READ loco=%d cv(%d)=%d/0x%x"), expectLoco, expectCV,data,data);
expectCallback(data);
expectCV=0;
}
}
if (expectCV) { // still waiting
expectWait--;
if (expectWait==0) {
DIAG(F("POM READ loco=%d cv(%d) FAIL"), expectLoco, expectCV);
expectCallback(-1);
expectCV=0;
}
}
}
auto v1=GETHIGHFLASH(decode,inbound[0]);
auto v2=(length>1) ? GETHIGHFLASH(decode,inbound[1]):INV;

View File

@ -22,6 +22,8 @@
#define Railcom_h
#include "Arduino.h"
typedef void (*ACK_CALLBACK)(int16_t result);
class Railcom {
public:
Railcom(uint16_t vpin);
@ -31,8 +33,16 @@ class Railcom {
>0: loco id
*/
void process(uint8_t * inbound,uint8_t length);
static void anticipate(uint16_t loco, uint16_t cv, ACK_CALLBACK callback) {
expectLoco=loco;
expectCV=cv;
expectWait=10; // channel3 packets
expectCallback=callback;
};
private:
static uint16_t expectCV,expectLoco,expectWait;
static ACK_CALLBACK expectCallback;
void noData();
uint16_t vpin;
uint8_t holdoverHigh,holdoverLow;