The Problem of Jitter in the DCS Signal
As discussed in one of the posts above, each sending of a command string by the TUI is preceeded by a single special "word" (combination of 1's & 0's). This special word has restrictions upon it. Certain strings of the 0's & 1's are more reliably recognized by the receiver in the locomotive. The explanation why this is so is complicated (& left out).
The same consideration applies to the decoding word stored in the receiver. So if the number of 0's & 1's is three, the decoding key is probably easily guessed. However, it is in the programming, and by copyrighting the programming the commercial production of competing receivers is prevented, or at least highly discouraged. However, a necessary function of the encoding is to make the sending of the information immune to all the electrical noise on the track-- roller sparks, wheel sparks, you name it.
Two or three features can assist in noise resistance. One is increasing the number of times the encoded signal is sent, by using a series of adjacent frequency bands. Then, if the sequences of 0's & 1's sent on each band is 31 pulses long, a set of 31 vectors are somehow* formed. A vector here is a line vector consisting of the 31 signal pulses. (* ..."Somehow" is an engineering technical term representing all possible explanations, used when the writer has totally forgotten. Its use is permitted when the explanation doesn't matter anyway.)
Now the rotational polar vector approach described in the posts above is an entirely different approach to explaining the DCS signal. Fortunately, within our lifetimes, the long proposed theory that all mathematical explanations of an engineering problem (or phenomenum) are in fact equivalent, was proven true. (I assume if the same answers result.) So we need not worry about one theory being right and the other wrong.
So the different approach I use gets one more quickly to jitter in the DCS signal. It is actually the patented explanation, and the number 31 also is an published by MTH. Now 31 is a choice that results in a set of 31 "orthogonal" vectors. Such vectors are each at right angles to the other 30 vectors. This means that a noise error in any one vector will not affect any of the other vectors.
The orthogonal vectors are the sets of three vectors, eight, fifteeen, 31 as here, 63, and so on. The formula is N orthogonal vectors = (2^n)-1, except zero. (Don't ask me why.) They are actually what are called degenerative cases of the more general theory (posted earlier here using the rotational vector approach) that includes all n vectors. As such, there are a lot of whiskers removed from the orthogonals' math, as we used to say.
The set of 3 vectors can be visualized as the familiar 3 vectors X, Y & Z of the space in which we live, each at right angles to the other 2.
The detection of whether a pulse is plus or minus depends on sampling it at a particular time. They travel at about 3/4s the speed of light, so the speed of the receiver hardly matters. But this speed is partly determined by the capacitance of the circuit. And very unfortunately for DCS, capacitance will vary with applied frequency. (This is a property of various material between the rails, while the standard formula assumes ideal invariants.)
The DCS frequencies lack a carrier, and so vary over a factor of about two orders of magnitude, or 10 x 10= 100 to one. This relative movement of the pulses among the various 0's & 1's vectors transmitted is called jitter. As a certain amount of this jitter builds up with distance the DCS signal becomes unreadable by the receiver.
In the case I investigated, an end-fed power block about 175 feet long lost DCS signal at the 140-foot point. A bulb was investigated for the inductance of its filament coil, and found to offset about 40 feet of track. I was truly amazed that the two were even in the same ballpark. BTW, it was the nano- ballpark.
I'll cover some practical suggestions shortly, related to the above insight.
--Frank
Okay some details and corrections.... for education purposes...
You seem be describing OFDM with parallel vectors and multiple transmit bands, which definitely not DCS. DCS is a CDMA scheme with polar NRZ signaling I don't know where the old tutorial went and I can't find it.... so let me plunk it here again (lightly updated to be in chronological order)
==========
Quick Refresher
===========
First of all DCS is a spread-spectrum technique which is a subset of CDMA (Code-Division Multiple Access). The specific technique used is called Direct-Sequence Spread Spectrum, or abbreviated DS/SS for short. Beyond model trains, DS/SS is employed in most wifi (802.11abgn,ac) and in wideband radar systems. It's large spreading ratio (spreading small data over larger bandwidth) is attractive for communication systems as it makes the link robust to multi-path, fast fade and channel distortions, while in radar the low energy density prevents it from easily being jammed or overrun by local transmitter leakage.
Okay so back to the trains:
The concept of spread-spectrum is that you use a long string of multiple bits (at a faster rate) to represent a single bit (at a slower rate). At the receiver you then correlate (multiply bitwise and add along the length of the packet ) the long string received against the known string of bits. The advantage of this over straight 1's and 0's is that even if a few bits are flipped due to interference and bad contact, the majority are left alone and so the data still makes it through. The number of bits that have to match to be considered a successful code detection is called the "Confidence interval" of the CDMA or DSS receiver system.
========================================================================
How it transmits -by example
========================================================================
Lets look at an example where the DCS TIU sends a command to the train. A command is typically a short packet of several bytes: 3F 2A 44 22 (something like this). It can be longer when downloading sound files, but for most functions (speed, bell, whistle, ...) it's pretty short, like 20 byte max. Note that for DCS the first byte in every packet is a constant value. Making the first value constant is common in DS/SS systems as it helps with packet detection and frame synchronization.
To make the math simpler lets do a simple 1 byte example...
We want to send byte "34" to the train through the DCS system.
So in base 2: 34 (hex) = 8'b00110100 (bin) (what we want to send)
As mentioned the spread spectrum replaces each bit with a string of multiple bits. In DCS the string of bits used to replace each bit in the packet is exactly 31 long. These 31 bit strings are often called PN codes (short for Pseudo-Noise), because they look like a noise signal in the frequency domain. For DCS only 2 PN codes are used (one for 1s and one for 0s) and they are complementary (meaning one code is the negation of the other). While this isn't the general case for DS/SS (any code could be used), I think DCS uses it to simply the correlator in the receiver.
So we will have 2 PN codes for DCS, each 31 bits long:
When I see a 0 in my packet I send: "0101011001001101111001011100110"
When I see a 1 in my packet I send: "1010100110110010000110100011001"
So in order to send 34 (00110100 in binary) the actual sequence of data streamed to the track will be:
(0101011001001101111001011100110)(0101011001001101111001011100110)(1010100110110010000110100011001)(1010100110110010000110100011001)(0101011001001101111001011100110)(1010100110110010000110100011001)(0101011001001101111001011100110(0101011001001101111001011100110)
Often in DS/SS systems we refer to each 1 or 0 actually transmitted as a "spreading-chip" (nothing do do with like microchip, it's just a name). So a "bit" is referring to the 1 or 0 at the packet level and a "chip" is referring to a 1 or 0 inside the PN code.
So since each PN code has 31 chips inside, and our packet is 1 byte (which is 8 bits) our entire sequence on the track should be: 31 X 8 = 248 spreading-chips. DCS has a "chip-rate" of 3.75 MHz meaning that every 1/3.75MHz = 266ns the next 1 or 0 in the transmission sequence appears on the track. Unlike WiFi or LTE, the sequence is not unconverted onto an RF carrier, it's just directly streamed out onto the track.
So in our example this 248 spreading-chip long code goes down the track and into the locomotive where it's picked up by the PS2/3 board in the locomotive.
Note that the above example is not the real PN codes, but they're down below somewhere.
If DS/SS is still confusing you, NI has a great tutorial here:
http://www.ni.com/white-paper/4450/en/
Okay great so how do we get our original code back?
==============
De-Spreading
==============
The process of turning the 31 spread-chip PN-codes back into each the single 0 or 1 in our packet is called de-spreading. Essentially we need to build a circuit that looks at the code on the track and compares it to the known code and identifies it as either the one or zero code.
Even though the real DCS system is 31 bits, I don't want to type all night so lets pretend its only 5 bits long.
Imagine we have a DCS-like 5-chip ds/ss system where
PN for 0 = "11011"
PN for 1 = "00100"
and we want to send the packet 101.
The transmitted sequence will be 00100 11011 00100
Clock Considerations:
Okay cool. So the first thing we need to think about is the clocking scheme. The chips in the transmitted sequence are updated at a rate of 3.75MHz meaning that every 266ns we will see the next symbol on the track. Now if we also clock the receiver at the same speed, in theory we will get 1 copy of each sample into our locomotive and can start comparing to the known PN codes. The trick is that in reality this does not work becasue your receiver will sample at Ttrain= n(266ns) + to1 (where to is the initial delay) while the TIU transmitter is putting the data onto the track at Ttiu= n(266ns) + To2. If you're really unlucky with To1 and To2 (which are simply a function of when you turn the TIU and train on) you could have the situation where the train receiver is looking at the track in the same instant the TIU is transitioning between values. Since the value is changing while you are trying to read it under this condition, you end up with a mess and nothing is reliably received. In comm system design we call this problem " clock synchronization", and the general set of solutions are called Clock-Data Recovery or "CDR" for short.
Basically there are 2 categories of techniques for CDR to align the transmitter and receiver clocks. One is called "phase-tracking" and the other is called "Phase-picking".
->Phase tracking solutions use a phase-lock loop to generate the receiver clock at the same frequency as the transmitter by directly locking on the transitions between chips. They then delay the locked clock by exactly T/2 (133ns in this case) to make sure the receiver is always sampling at the instant in the middle the last and next transition of the transmitter:
TX Clock edges: X X X X X (time where data changes)
RX Clock edges: X X X X (time where data is read)
It's not used in DCS but it's the 99.999% more common way to solve clock synchronization, if you open a modern Qualcomm baseband modem, this is what's in there.
-> Okay so phase-picking (the one that DCS uses). What we do in phase-picking is say we know the data is changing every 266ns, so if I take samples at 133ns (twice as fast), I know that at least one of every two samples will be at a time when the data is not changing.
TX Clock edges: X X X X (time where data changes)
RX Clock edges: X X X X X X X X (time where data is read)
So what we do is sample at twice the rate (3.75MHz X 2 = 7.5 MHz) and then we are covered... sort of. Time for more of the hardcore details.... In general you can imagine with this approach that if a given sample n is bad, then the next sample n+1 is probably okay, and the sample after that is probably bad again. Basically we assume that either (all the even samples we took) , or (all the odd samples we took) will be good. So we actually build two receivers in parallel, one looking at the even values and one looking at the odd values.
Okay so this assumption has 1 big conditional. It's only true if one clock frequency is exactly twice the other. This is of course not true in practice as the clocks will drift a little. So right now we have spreading-chips coming every 266ns and we're sampling at 133ns. Lets say for example the Rx clock was a bit off so we had 266ns and 132ns. This means in the RX two samples will be 132X2 = 264ns, meaning we will start sampling (266-264)=2ns early on the next spreading-chip. 2ns compared to 266ns so that is not a big deal. So the next chip was expected to start at 266ns but really starts at 264ns and then it's only 264ns long too, so when we expected to end 2 chips at 266X2=532ns we actually ended at only 528ns (4ns error). The longer we make the packet the more the chip-to-chip slip (called cycle slippage in communication design). Typically we design what we call the "coherence span", which is the total number of chips you can have over which the slip is less than half of the chip time at the end of the entire sequence. In this case the chip time is 266ns (and a half-chip time is 133ns), and we're slipping 2ns each chip so 133/2= 66 chips is the most we can send for each packet. In reality 1ns/133ns is a really big error, typically in ds/ss systems we talk about clock frequency errors in the parts per million. Still, the "coherence-span" is the fundamental parameter in a communication system that limits how long a packet can be.
For those interested: Phase tracking also has a coherence-span, which is related to how well the phase-lock loop can hold phase over time (called phase noise or timing jitter).
Okay cool, so that's the clocking out of the way. On to the decoding
Decoding part:
Okay so now we sampled the incoming packet correctly. Remember from here on we actually do everything on two copies (then even samples and the odd samples), but I will leave that out of this part to make it easier to understand.
So thinking about our DCS-like code coming in to the receiver that we sent in the above example:
00100 11011 00100
It will actually be time dependent at the receiver, that is we will receive one byte at a time. We can use a thing called a shift register that stores bits in the sequence they were received in:
[D4]->[D3]->[D2]->[D1]->[D0]
This is a 5 bit shift register.... when the first clock comes the track data moves into D5, whatever was in D5 before moves to D4, what was in D4 moves into D3 and so on down to D0. The data that was in D0 is just forgotten.
So imagine we are receiving a sequence like 01001 as an example. In time what will happen is
start: D4=X D3=X D2=X D1=X D0=X
after 1 clock: D4=1 D3=X D2=X D1=X D0=X
after 2 clock: D4=0 D3=1 D2=X D1=X D0=X
after 3 clock: D4=0 D3=0 D2=1 D1=X D0=X
after 4 clock: D4=1 D3=0 D2=0 D1=X D0=X
after 5 clock: D4=0 D3=1 D2=0 D1=0 D0=1
(x are values we don't know.... because we don't know what was inside to begin with)
So what we do next is cool. We use XNOR gates.
An XNOR gate is a circuit with 2 inputs and 1 output. If the 2 inputs are the same (both 0 or both 1) it outputs a 1, if they are different it outputs a zero.
1 XOR 1 = 1 0 XOR 1 = 0 0 XOR 1 = 0 0 XOR 0 = 1
So we can put the XOR between the known PN_code and the shift register. When they match we can write down that we received a 1 or 0 accordingly. Mathwise:
Our PN_code is {PN4 PN3 PN2 PN1 PN0}
When we have (PN4 XOR D4)=1 AND (PN3 XOR D3)=1 AND (PN2 XOR D2)=1 AND (PN1 XOR D1)=1 AND (PN0 XOR D0)=1 it means we have a match. The next step is we add up all the xor results.
So lets say our PN code was the 11011 from above and we had a 01010 in the shift register at this instant. Then the XOR output would be
11011
01010
=====
01110 (0 when they don't match, 1 when they do)
We can add these up to get 0+1+1+1+0 = 3
We call this summation the "code-correlation".
So the more numbers that match, the closer the input code is to the known PN_code in our memory and the higher our code correlation. Now remember that our PN_code for 0 is the opposite of the PN_code for 1.
So if the result is totally different than our PN_code for 1, the code-correlation will be 0 (which means the shift register data exactly matches our code for 0).
What's the Probability of false detection of our PN code:
This is where it gets interesting if you want to do some statistical analysis....
The real DCS code is 31 chips.
Now imagine we pick 31 random values of 1 and 0 and assemble them into a chip code. Basically this is the same as guessing 1 or 0 thirty-one times. You would expect about 50% of the bits you you guessed to be right which means of the 31 chips, about 15 would be correct. Going through the shift register and XOR, this means that the code-correlation will have a statistical mean somewhere around 31/2 (so about 15.5).
Short hand note: often we call code-correlation "Cx" for short. So some statistics now
we would say the expected value of Cx or E(Cx) = 15.5
So choosing 1 or 0 has equal probability (called a binomial probability distribution). The statistical variance Var(Cx) is going to be (1-0.5)/0.25 or about 2, or a standard deviation of about sqrt(2). This means that if we randomly pump data in 99% of the time the Cx will land within 3 standard deviations of the mean (IE between 15.5 - 3Xsqrt(2) and 15.5+3Xsqrt(2)) or (11.3 to 19.7). So if we consider 6 standard deviations next ( 6sqrt(2) = 8.4) that means that a random stream of data has a 1 in 506,797,356 chance of providing a Cx outside the range of 7.1 to 23.9. What this is really saying is there is less than a 1 in 500 million chance of accidently matching (31-7) = 24 bits or more.
Similarly for completeness:
Matching 25 bits or more is about a 1 in 13 billion chance
Matching 27 bits or more is about a 1 in 16.2 trillion chance
Okay so the chip time was 266ns right? (266x 10^-9 s) so receiving 16.2 trillion chips would take 4 million seconds (about 50 days). So unless you run the train for 50 days straight you will never see enough chips to have 27 spreading-chips matched randomly....
Confidence Threshold:
Right okay so all the statistics was to set up this concept. Remember we said that when:
Cx=0 means all the bits are matching the PN_code for 0
Cx=31 means all the bits are matching the PN_code for 1.
Well sometimes the track contacts can glitch or we go over a turnout switch and lose a bit or something... so is it really necessary to only detect when all of the code matches? Remember that one in 16.2 trillion chance above.
So we define a confidence threshold value called "Ct"... basically a number that says "if more than this many bits match" we still take it as a 1 or 0 in our packet.
Right so back to the 5 chip example:
Lets set the confidence threshold to 4
so if we have a PN_code of 11011
and we receive
11011 (the right code)
then the Cx=5 and (Cx=>Ct) so we take the number.
Similarly
if there's a glitch and receive
11(1)11 (one flipped chip)
then the Cx=4 and still (Cx=>Ct) so we take the number.
This is the big advantage of ds/ss is that it's error tolerant. So then we get into fundamental optimization concepts. In the DCS system Ct has values from 15 to 31. (Its not 0 to 31 because Cx going from 0 to 15 means we're matching the 0 code instead of the 1 code). If we make Ct very high ... say 30 or 31, then the probability of random error is very low, like 1 in quadrillions, but the tolerance to flipped bits is low (none or only 1 bit can be flipped) , alternatively if we lower Ct to like 25, then we can tolerate a lot of errors, but the probability of a false detection is also going up a lot... So you have to design a Ct that's reasonable at both ends of the scale. The "signal strength" you see on the remote is actually the Cx values added up for all the bits in the packet with some scaling applied.
So usually once you've detected those 1's and 0s for the packet, you put them into an packet-buffer with an index register that counts how many bits you've received so far. A separate circuit (not discussed here... maybe later) called a command decoder recognizes those packet sequences as commands. Each time a command is detected, the command decoder resets the index counter to 0 and clears the packet buffer so that the ds/ss receiver becomes ready to receive the next packet sequence. Unfortunately all of these are inside the programmable FPGA on the PS2/3 boards so they aren't accessible unless you make your own on an FPGA.
Luckily for you, if you have an FPGA, I have the RTL code attached here to play with. Just a basic verilog a basic DCS transmitter and receiver are attached. These have been tested on my MTH TIUs and engines . DCS_decoder.v is the receiver and DCS_spoof.v is the TX. Here's some videos of exactly these RTLs running on an ARTY 7 FPGA:
DCS Decoder Example
DCS_Transmitter Example