186 Zeilen
6.4 KiB
C

//Z21 DCC RailCom Decoder
//Dekodierung globaler Railcomdaten am Serial3 (MEGA only!)
//
//Copyright (c) by Philipp Gahtow, year 2021
//--------------------------------------------------------------
#if defined(DCCGLOBALDETECTOR) && defined(DCC)
uint16_t RailcomCVAdr = 0; //init global RailCom detector for POM
//--------------------------------------------------------------
#if defined(MEGA_MCU)
/*
void notifyCVPOMRead(uint16_t Adr, uint8_t value) {
#if defined(LAN) || defined(WIFI) || defined(ESP_WIFI)
z21.setCVPOMBYTE(Adr, value);
#endif
}
*/
#define RCSerial Serial3 //Serial Port that we will listen to for RailCom Data
//--------------------------------------------------------------
byte RailComGetCV = false; //try to receive a CV value
byte RailComReadFirst = true;
byte RailComReadData = 0; //Save the first 2 bit data
byte RailComReadLastCV = 0xFF; //Save the last read CV value
byte RailComCVRead = false; //receive a CV value
byte RailComCVTime = 0; //cycle time
uint16_t RailComReadAdr = 0; //Adress read over RailCom
//--------------------------------------------------------------
//init the Serial interface for receiving RailCom
void RailComSetup(void) {
RCSerial.begin(250000); //Read Railcom Message at 250KBit
}
//--------------------------------------------------------------
//Decoding RailCom Received Data
byte RailComDecodeInData (void) {
switch (RCSerial.read()) {
case B10101100: return 0x00;
case B10110010: return 0x10;
case B01010110: return 0x20;
case B11000110: return 0x30;
case B10101010: return 0x01;
case B10110100: return 0x11;
case B01001110: return 0x21;
case B11001100: return 0x31;
case B10101001: return 0x02;
case B10111000: return 0x12;
case B01001101: return 0x22;
case B01111000: return 0x32;
case B10100101: return 0x03;
case B01110100: return 0x13;
case B01001011: return 0x23;
case B00010111: return 0x33;
case B10100011: return 0x04;
case B01110010: return 0x14;
case B01000111: return 0x24;
case B00011011: return 0x34;
case B10100110: return 0x05;
case B01101100: return 0x15;
case B01110001: return 0x25;
case B00011101: return 0x35;
case B10011100: return 0x06;
case B01101010: return 0x16;
case B11101000: return 0x26;
case B00011110: return 0x36;
case B10011010: return 0x07;
case B01101001: return 0x17;
case B11100100: return 0x27;
case B00101110: return 0x37;
case B10011001: return 0x08;
case B01100101: return 0x18;
case B11100010: return 0x28;
case B00110110: return 0x38;
case B10010101: return 0x09;
case B01100011: return 0x19;
case B11010001: return 0x29;
case B00111010: return 0x39;
case B10010011: return 0x0A;
case B01100110: return 0x1A;
case B11001001: return 0x2A;
case B00100111: return 0x3A;
case B10010110: return 0x0B;
case B01011100: return 0x1B;
case B11000101: return 0x2B;
case B00101011: return 0x3B;
case B10001110: return 0x0C;
case B01011010: return 0x1C;
case B11011000: return 0x2C;
case B00101101: return 0x3C;
case B10001101: return 0x0D;
case B01011001: return 0x1D;
case B11010100: return 0x2D;
case B00110101: return 0x3D;
case B10001011: return 0x0E;
case B01010101: return 0x1E;
case B11010010: return 0x2E;
case B00111001: return 0x3E;
case B10110001: return 0x0F;
case B01010011: return 0x1F;
case B11001010: return 0x2F;
case B00110011: return 0x3F;
case 0x0F: return 0xF0; //ACK
}
return 0xFF;
}
//--------------------------------------------------------------
//Check if we receive data?
void RailComRead(void) {
if (RailComGetCV) { //need to read data?
RailComCVTime++;
while (RCSerial.available()) { //is there serial data in buffer?
byte data = RailComDecodeInData(); //read Railcom Data and decode Railcom Data
if (data < 0x40) { //gültige Railcom Message empfangen
if (RailComReadFirst) {
RailComReadData = data; //Save first Byte of Data
if ((data >> 2) < 3) //app:pom, app:adr_low, app:adr_high -> read only 12 Bit!
RailComReadFirst = false;
}
else {
RailComReadFirst = true;
byte RailComID = RailComReadData >> 2; //Save ID
RailComReadData = (RailComReadData << 6) | data; //first 2 Bit and add next 6 Bit
if (RailComID == 0) { //app:pom
RailComCVTime = 25; //Reset Timer!
RailComReadLastCV = RailComReadData;
RailComCVRead = true;
}
else if (RailComID == 1) { //app:adr_high
RailComReadAdr = (RailComReadData << 8) | (RailComReadAdr & 0xFF);
}
else if (RailComID == 2) { //app:adr_low
RailComReadAdr = (RailComReadAdr & 0xFF00) | RailComReadData;
}
}
}
else RailComReadFirst = true;
}
if (RailComCVTime == 0) { //TIMEOUT?
RailComGetCV = false; //Stop reading! ERROR!
if (RailComCVRead == true) {
RailComCVRead = false;
#if defined(LAN) || defined(WIFI) || defined(ESP_WIFI)
z21.setCVPOMBYTE(RailcomCVAdr, RailComReadLastCV);
#endif
#if defined(RCDEB)
Debug.print(F(" result: A"));
Debug.print(RailComReadAdr);
Debug.print(" CV");
Debug.print(RailcomCVAdr+1);
Debug.print(" = ");
Debug.println(RailComReadLastCV);
#endif
}
else {
#if defined(LAN) || defined(WIFI) || defined(ESP_WIFI)
z21.setCVNack(); //Antwort: LAN_X_CV_NACK
#endif
#if defined(RCDEB)
Debug.println(" RC ERROR");
#endif
}
}
}
}
//--------------------------------------------------------------
//Start Reading Data!
void RailComStart(void) {
while(RCSerial.available()){RCSerial.read();} //remove all rubish data
RailComGetCV = true; //start reading RailCom Data
RailComReadLastCV = 0xFF; //Reset the last Value
RailComCVTime = 0; //Reset the cycle time
RailComReadAdr = 0;
RailComRead(); //Try to read data...
}
#endif //End MEGA Serial
//--------------------------------------------------------------
#endif