DCC, Digital Command Control, is THE standard for digital control of model railroads. It is based on developments of the german company Lenz and was declared a standard by the NMRA and in the meantime got a lot of enhancements and extensions.
The +/-12 volt signal on the rail is a stream of short (binary 1) and long (binary 0) pulses, for example

More info you can find on wikipedia.org - Digital_Command_Control - and lots of details, open hardware designs and open source software on OpenDCC .
| The author of this website is currently building a few - very simple - projects around DCC, like | |
| a throttle with interface to the Lenz system | ![]() |
| a very basic and simple DCC command station (not yet finished) | |
| a "processing" program for the offline evaluation of DCC signals. | |
| ..... | |
| This is a very simple "offline" decoder for the analysis of DCC signals. It needs sampling of the signal on the rails every 10 microseconds, low=0 and high=1 (or vice versa, because the signal is symmetric), one line per sample. (Language "Processing"). The sampling was done with the help of a PC-USB logic analyser. |
| !!! the program is written in the "processing" language !! see www.processing.org |
/* Detect_dcc_signal
This "processing" program analyses a "DCC" signal (see NMRA pages).
As input it needs a number of lines with the info "0" (signal low on rails) or "1" (signal high on rails), sampled every 10 microseconds
one line per sample like:
1
1
0
1
0
......
the output is the DCC packets binary info, "S" denoting Startbit, "E" denoting Endbit
for example
(22ms) S 11111111 S 00000000 S 11111111 E
(32ms) S 00101000 S 00111111 S 01111111 S 01101000 E
BYTE1 BYTE2 BYTE3 CHECKSUM (=XOR of the other BYTES)
Copyright (C) 2009 Michael Blank
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
int timer=0;
String infile="c:\\users\\mblank\\dcc7-smax-f0f1.csv";
void setup() {
;
}
boolean step_down(String d[], int n) {
// detect HIGH to LOW transition
if ((d[n].charAt(0) =='0') && (d[n-1].charAt(0) == '1')) {
return true;
} else {
return false;
}
}
boolean step_up(String d[], int n) {
// detect LOW to HIGH transition
if ((d[n].charAt(0) =='1') && (d[n-1].charAt(0) == '0')) {
return true;
} else {
return false;
}
}
void draw() {
String data[]= loadStrings(infile);
// load input file into String array, input is 1=high, 0=low
boolean flag = false;
boolean d_flag = false; // used within data packet
int count = 0;
int count_bytes = 0;
int count_ones = 0; // used for detecting the preamble (count_ones >10)
println("sampling rate must be 10us !!");
println("no of samples is: "+data.length);
for (int i=1; i< data.length; i++) {
timer++;
// detect high->low steps only, then count until 0->1
if (step_down(data,i)) {
flag = true;
}
if (flag == true) { // increase counter when last input was LOW
count++;
}
// check for end of LOW, decide whether 0 (=long) or 1 (=short) was detected
if (step_up(data,i)) {
flag = false; // don't count LOWs any longer
// end of pulse reached
if (count > 8) {
// this is a logical ZERO
if (count_ones >10) { // then preamble just ends
print("("+timer/100+"ms) ");
print(" S ");
count_ones =0; //reset
count_bytes =0; // start counting databytes
d_flag = true;
} else if (count_bytes == 8) { // then data packet ends!!!
print(" S ");
count_bytes = 0;
count_ones =0; //reset
} else { // in the middle of data packet
print("0");
count_bytes++;
count_ones =0; //reset
}
} else {
// this is a "1", so determine whether part of data packet or part of preample
if (d_flag == true ) {
if (count_bytes == 8) { // then data packet ends!!!
println(" E ");
count_bytes = 0;
count_ones =0; //reset
d_flag = false; // last data packet was sent
} else { // not the last bit
print("1");
count_bytes++;
}
} else {
//print("P");
; // don't print the simple preamble packets
}
count_ones++;
}
count = 0;
}
}
exit();
}