mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-22 23:56:13 +01:00
POM Read
This commit is contained in:
parent
68809fa8d5
commit
a0a503ad7d
19
DCC.cpp
19
DCC.cpp
|
@ -389,6 +389,25 @@ void DCC::writeCVByteMain(int cab, int cv, byte bValue) {
|
||||||
DCCWaveform::mainTrack.schedulePacket(b, nB, 4);
|
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
|
// writeCVBitMain: Write a bit of a byte with PoM on main. This writes
|
||||||
// the 5 byte sized packet to implement this DCC function
|
// the 5 byte sized packet to implement this DCC function
|
||||||
|
|
3
DCC.h
3
DCC.h
|
@ -64,6 +64,8 @@ public:
|
||||||
static uint8_t getThrottleFrequency(int cab);
|
static uint8_t getThrottleFrequency(int cab);
|
||||||
static bool getThrottleDirection(int cab);
|
static bool getThrottleDirection(int cab);
|
||||||
static void writeCVByteMain(int cab, int cv, byte bValue);
|
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 writeCVBitMain(int cab, int cv, byte bNum, bool bValue);
|
||||||
static void setFunction(int cab, byte fByte, byte eByte);
|
static void setFunction(int cab, byte fByte, byte eByte);
|
||||||
static bool setFn(int cab, int16_t functionNumber, bool on);
|
static bool setFn(int cab, int16_t functionNumber, bool on);
|
||||||
|
@ -128,6 +130,7 @@ private:
|
||||||
// NMRA codes #
|
// NMRA codes #
|
||||||
static const byte SET_SPEED = 0x3f;
|
static const byte SET_SPEED = 0x3f;
|
||||||
static const byte WRITE_BYTE_MAIN = 0xEC;
|
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_BIT_MAIN = 0xE8;
|
||||||
static const byte WRITE_BYTE = 0x7C;
|
static const byte WRITE_BYTE = 0x7C;
|
||||||
static const byte VERIFY_BYTE = 0x74;
|
static const byte VERIFY_BYTE = 0x74;
|
||||||
|
|
|
@ -481,6 +481,14 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||||
DCC::writeCVByteMain(p[0], p[1], p[2]);
|
DCC::writeCVByteMain(p[0], p[1], p[2]);
|
||||||
return;
|
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>
|
case 'b': // WRITE CV BIT ON MAIN <b CAB CV BIT VALUE>
|
||||||
if (params != 4)
|
if (params != 4)
|
||||||
break;
|
break;
|
||||||
|
@ -1417,6 +1425,12 @@ void DCCEXParser::callback_R(int16_t result)
|
||||||
commitAsyncReplyStream();
|
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) {
|
void DCCEXParser::callback_Rloco(int16_t result) {
|
||||||
const FSH * detail;
|
const FSH * detail;
|
||||||
if (result<=0) {
|
if (result<=0) {
|
||||||
|
|
|
@ -68,7 +68,8 @@ struct DCCEXParser
|
||||||
static void callback_W(int16_t result);
|
static void callback_W(int16_t result);
|
||||||
static void callback_W4(int16_t result);
|
static void callback_W4(int16_t result);
|
||||||
static void callback_B(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_Rloco(int16_t result);
|
||||||
static void callback_Wloco(int16_t result);
|
static void callback_Wloco(int16_t result);
|
||||||
static void callback_Wconsist(int16_t result);
|
static void callback_Wconsist(int16_t result);
|
||||||
|
|
28
Railcom.cpp
28
Railcom.cpp
|
@ -145,6 +145,10 @@ Railcom::Railcom(uint16_t blockvpin) {
|
||||||
lastChannel1Loco=0;
|
lastChannel1Loco=0;
|
||||||
vpin=blockvpin;
|
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.
|
// 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 v1=GETHIGHFLASH(decode,inbound[0]);
|
||||||
auto v2=(length>1) ? GETHIGHFLASH(decode,inbound[1]):INV;
|
auto v2=(length>1) ? GETHIGHFLASH(decode,inbound[1]):INV;
|
||||||
|
|
10
Railcom.h
10
Railcom.h
|
@ -22,6 +22,8 @@
|
||||||
#define Railcom_h
|
#define Railcom_h
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
typedef void (*ACK_CALLBACK)(int16_t result);
|
||||||
|
|
||||||
class Railcom {
|
class Railcom {
|
||||||
public:
|
public:
|
||||||
Railcom(uint16_t vpin);
|
Railcom(uint16_t vpin);
|
||||||
|
@ -31,8 +33,16 @@ class Railcom {
|
||||||
>0: loco id
|
>0: loco id
|
||||||
*/
|
*/
|
||||||
void process(uint8_t * inbound,uint8_t length);
|
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:
|
private:
|
||||||
|
static uint16_t expectCV,expectLoco,expectWait;
|
||||||
|
static ACK_CALLBACK expectCallback;
|
||||||
void noData();
|
void noData();
|
||||||
uint16_t vpin;
|
uint16_t vpin;
|
||||||
uint8_t holdoverHigh,holdoverLow;
|
uint8_t holdoverHigh,holdoverLow;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user