|
DCC Paket Dekoder Das Format wurde von der NMRA definiert und ein Paket kann wie folgt aussehen:
Das Bild stammt aus dem NMRA Dokument: S 9.2 vom Juli 2004 Der Platine mit dem PIC Prozessor macht das was der Titel schon sagt, das DCC Signal wird ab Zentrale dekodiert und zwar so, dass man es auch lesen kann: 3;60;63 Den Datenstrom kann man mit dem Programm Hyperterminal
anschauen, d.h. die Daten kommen in hexadezimaler und als Text über die
Schnittstelle. using System; using System.IO; using System.IO.Ports; using System.Windows.Forms; using System.Collections.Generic; using System.Text; namespace SerialPortExample
{
class SerialPortProgram
{
// Create the serial port with basic settings
private SerialPort m_port = new SerialPort("COM1", 115200);
// The streamwriter to save the trace information to the disk
private StreamWriter m_streamwriter = new StreamWriter("Lenz_cu.txt");
[STAThread]
static void Main(string[] args)
{
// Instantiate this class
new SerialPortProgram();
}
private SerialPortProgram()
{
try
{
m_streamwriter.AutoFlush = true;
Console.WriteLine("Avaliable ports::");
foreach (string s in SerialPort.GetPortNames()) Console.WriteLine(s); m_port.ReceivedBytesThreshold = 1;
m_port.Handshake = Handshake.None;
Console.WriteLine("Incoming Data:");
// Attach a method to be called when there is data waiting in the port's buffer
m_port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
// Begin communications
m_port.Open();
// Enter an application loop which keeps this thread alive
Application.Run();
}
catch (Exception ex)
{
MessageBox.Show( ex.Message);
}
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
// Show all the incoming data in the port's buffer
//string Ls_string = m_port.ReadLine();
//m_streamwriter.WriteLine(Ls_string);
//Console.WriteLine(Ls_string);
SerialPort port = (SerialPort)sender; // binary mode
int bytesAvailable = m_port.BytesToRead;
byte[] data = new byte[bytesAvailable];
m_port.Read(data, 0, data.Length);
for (int n = 0; n < bytesAvailable; n++)
{
// extract the bits from the stream...
int Li_time = data[n];
string Ls_string = " " + Li_time.ToString() + " ";
Console.Write( Ls_string );
m_streamwriter.Write(Ls_string);
eDCC_BitState L_bit_state = ExtractBit(Li_time);
Insert_dcc_bit(L_bit_state);
}
}
catch (IOException ex)
{
m_streamwriter.WriteLine(ex.Message);
Console.WriteLine("IOException: " + ex.Message);
}
catch (Exception ex)
{
m_streamwriter.WriteLine(ex.Message);
Console.WriteLine(ex.Message);
//MessageBox.Show(ex.Message);
}
}
// half bit times
private int m_bit1_min = 51;
private int m_bit1_max = 65;
private int m_bit0_min = 95; private int m_bit0_max = 9900; // not yet used, the max bit streching time allowed //private int m_0_duration = 12000; private enum ePacket_decoding_state
{
eExtract_preamble, // each half bit will be counted
eExtract_data // only full and valid bits will be processed
}
private enum eDCC_BitState // Named bit state
{
eUndefined_bit_state, // undefined
eSpike_bit, // a spike or other error situation from the cu
eZero_bit, // a valid zero bit time
eOne_bit // a valid one bit time
}
private byte[] m_dcc_command = new byte[] { 0, 0, 0, 0, 0, 0, 0 };
private eDCC_BitState m_last_bit_state = eDCC_BitState.eUndefined_bit_state; private ePacket_decoding_state m_decoding_state = ePacket_decoding_state.eExtract_preamble; private int m_half_bit_count = 0; private int m_byte_count = 0; private int m_preamble_count = 0; private int m_packet_bit_count = 0; // xtract the bits from the nmra bit stream
private eDCC_BitState ExtractBit(int i_bit_time)
{
eDCC_BitState L_bit_state = eDCC_BitState.eUndefined_bit_state;
if (m_bit1_min <= i_bit_time && m_bit1_max >= i_bit_time)
{
// a bit '1' catched
L_bit_state = eDCC_BitState.eOne_bit;
}
else if (m_bit0_min <= i_bit_time && m_bit0_max >= i_bit_time)
{
// a bit '0' catched
L_bit_state = eDCC_BitState.eZero_bit;
}
else
{
// a spike or a faulty bit from the command station
L_bit_state = eDCC_BitState.eSpike_bit;
Console.WriteLine( "???: " + i_bit_time.ToString() );
}
return L_bit_state;
}
private void Insert_dcc_bit( eDCC_BitState i_bit_state )
{
// process only valid bist
if (i_bit_state == eDCC_BitState.eOne_bit || i_bit_state == eDCC_BitState.eZero_bit)
{
switch (m_decoding_state)
{
case ePacket_decoding_state.eExtract_preamble:
InsertPreamble(i_bit_state);
break;
case ePacket_decoding_state.eExtract_data:
m_half_bit_count++;
// now we process the dcc "half bits"
switch (m_half_bit_count)
{
case 1:
m_last_bit_state = i_bit_state;
// after the second half bit we know what to do
return;
case 2:
// do the normal processing later on...
m_half_bit_count = 0;
break;
}
// matching bit pair
if ( m_last_bit_state == i_bit_state )
InsertPacketBit(i_bit_state);
else
{
//Console.WriteLine("Error decoding state: bit pairs do not match!");
Reset_packet_decoder();
}
break;
default:
Console.WriteLine("Error decoding state: " + m_decoding_state.ToString());
// Reset state engine
Reset_packet_decoder();
break;
}
m_streamwriter.WriteLine(i_bit_state.ToString());
//Console.WriteLine(i_bit_state.ToString());
}
else
{
Console.WriteLine( "Error bit: " + i_bit_state.ToString());
// Reset state engine
Reset_packet_decoder();
}
}
private void InsertPreamble(eDCC_BitState i_bit_state)
{
if (i_bit_state == eDCC_BitState.eOne_bit)
{
// normal preamble bit
m_preamble_count++;
}
else
{
// we are not counting half bits
if (m_preamble_count > 10)
{
// sync on the last zero bit pair
if ( m_last_bit_state == i_bit_state )
m_decoding_state = ePacket_decoding_state.eExtract_data;
m_last_bit_state = i_bit_state;
}
else
{
// not enough preamble bits received!
//Console.WriteLine("Error decoding state: not enough preamble bits received!");
Reset_packet_decoder();
}
}
}
private void InsertPacketBit(eDCC_BitState i_bit_state)
{
switch (m_packet_bit_count)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
// small optimisation
// process only only bits which are set
if (i_bit_state == eDCC_BitState.eOne_bit)
{
double Ld_x = 2;
// we receive the high bit first
double Ld_y = 7 - m_packet_bit_count;
double Ld_val = Math.Pow(Ld_x, Ld_y);
byte Lb_val = (byte) Ld_val;
m_dcc_command[m_byte_count] |= Lb_val;
}
m_packet_bit_count++;
break;
case 8:
m_byte_count++;
// the packet byte end bit has to a 'zero'
if (i_bit_state == eDCC_BitState.eZero_bit)
{
// next packet byte please
m_packet_bit_count = 0;
}
else
{
// a valid dcc packet has been received
Print_dcc_packet();
Reset_packet_decoder();
}
break;
default:
Console.WriteLine("Error decoding state: invalid packet bit counter!");
break;
}
}
private void Print_dcc_packet()
{
string Ls_string = "DCC packet received: ";
Console.Write(Ls_string);
m_streamwriter.Write(Ls_string);
for (int Li_loop = 0; Li_loop < m_byte_count; Li_loop++)
{
byte packet_byte = m_dcc_command[Li_loop];
Console.Write("{0} ", packet_byte);
m_streamwriter.Write("{0} ", packet_byte);
}
Console.WriteLine();
m_streamwriter.WriteLine();
}
// initial preamble counting state
private void Reset_packet_decoder()
{
int Li_elems = m_dcc_command.Length;
for (int Li_loop = 0; Li_loop < Li_elems; Li_loop++)
{
m_dcc_command[Li_loop] = 0;
}
m_half_bit_count = 0; m_byte_count = 0; m_preamble_count = 0; m_packet_bit_count = 0; m_decoding_state = ePacket_decoding_state.eExtract_preamble; m_last_bit_state = eDCC_BitState.eUndefined_bit_state; } } }
|