Monday, July 8, 2013

An Interrupt based DCC Decoder

In the early days of DIY DCC decoders, the preferred method of DCC decoding logic was to write precisely metered sections of hand-written assembly code that sampled the DCC input. These were based on the venerable 16C84 running at 4MHz.

But with modern PICs running at 32 MHz and over, it is possible to write an interrupt driven DCC decoder. This means no more intricately hand-coded assembly. You could write it in C without worrying too much about the code generated - within reason. So what is a good interrupt period to sample the DCC input? OK, 22us. But how accurate does this period have to be? Can we use the internal oscillator in a PIC? Yes, we can!

DCC Input Format

This is what a DCC signal looks like.

As defined by the NMRA S9.1 standard, the signal is bipolar and each bit is sent as a high and low of equal durations. The 0 and 1 have different durations. Let us look at the bits individually.

The standard for the duration of the pulses when sent out by a command station and what is treated as valid when received by a decoder are different to give that additional margin of safety. As we are looking at decoding the bit stream, we will look at the second set. A 1 can ranging between 52us and 64us. Note that this is one half of the signal, the other half will be the same. A 0 can range from 90us to 10,000us.

Sampling the DCC Input

A simple 10k/4K7 voltage divider feeds the PIC input. The negative part is clamped by the internal PIC diode. The high is sampled. This samples half the waveform and ignores the low.

The sampling is done as part of the ISR. Count the number of samples that the output is high for and analyse the results. The crux of it is differentiating between the widest 1 (64us) and the narrowest 0 (90us). The minimum count is when the sample has just missed the start of the pulse. The maximum count is when it just catches the start of the pulse. The maximum count is the minimum count plus one.

Let us look at a sampling period of 22us in the diagram below. On the left, the sampling has just missed the start of the pulse and the pulse is 64us long. The sampling will happen at 22us, 44us, 66us, etc. The first two samples will see a high and the count detected will be 2. This is the minimum count detected. On the right, the sampling has just found the start of the pulse. The first three samples will see a high and the count detected will be 3. This is the maximum count. The maximum count is one more than the minimum count. If the pulse is 90us long, the high will be seen at 22us, 44us, 66us and 88us. The minimum count will be 4. As the maximum count for a one is 3 and the minimum count for a zero is 4, a 22us sampling interval will work.

So what is the ideal sampling rate? How much of a variation in the sampling rate can be tolerated? Not knowing the mathematical basis behind this, I took the brute force approach of using an Excel spreadsheet. A range of sampling frequencies from 10us to 25us in 0.1us steps is the starting point. For a given duration, the minimum sampling count is FLOOR(duration/sampling period). The maximum is that value plus one. The spreadsheet looks like this.

PeriodNarrowest 1Widest 1Narrowest 0Widest 0Diff in
Count
MinMaxMinMaxMinMaxMinMax
105667910100010012
10.15667899909911
10.25667899809811
10.35667899709711
10.45667899619621
10.54567899529531
10.64567899439441
10.74556899349352
10.84556899259262
10.94556899179182
114556899099102
11.14556899009012
11.24556898928932
11.34556788848851
11.44556788778781
11.54556788698701
11.64556788628631
11.74556788548551
11.84556788478481
11.94556788408411
124556788338341
12.14556788268271
12.24556788198201
12.34556788138141
12.44556788068071
12.54556788008011
12.64556787937941
12.74556787877881
12.84556787817821
12.94545677757761
134545677697701
13.13445677637641
13.23445677577581
13.33445677517521
13.43445677467471
13.53445677407411
13.63445677357361
13.73445677297301
13.83445677247251
13.93445677197201
143445677147151
14.13445677097101
14.23445677047051
14.33445676997001
14.43445676946951
14.53445676896901
14.63445676846851
14.73445676806811
14.83445676756761
14.93445676716721
153445676666671
15.13445566626630
15.23445566576580
15.33445566536540
15.43445566496500
15.53445566456460
15.63445566416420
15.73445566366370
15.83445566326330
15.93445566286290
163445566256260
16.13434566216221
16.23434566176181
16.33434566136141
16.43434566096101
16.53434566066071
16.63434566026031
16.73434565985991
16.83434565955961
16.93434565915921
173434565885891
17.13434565845851
17.23434565815821
17.33434565785791
17.42334565745751
17.52334565715721
17.62334565685691
17.72334565645651
17.82334565615621
17.92334565585591
182334565555561
18.12334455525530
18.22334455495500
18.32334455465470
18.42334455435440
18.52334455405410
18.62334455375380
18.72334455345350
18.82334455315320
18.92334455295300
192334455265270
19.12334455235240
19.22334455205210
19.32334455185190
19.42334455155160
19.52334455125130
19.62334455105110
19.72334455075080
19.82334455055060
19.92334455025030
202334454995000
20.12334454974980
20.22334454954960
20.32334454924930
20.42334454904910
20.52334454874880
20.62334454854860
20.72334454834840
20.82334454804810
20.92334454784790
212334454764770
21.12334454734740
21.22334454714720
21.32334454694700
21.42323454674681
21.52323454654661
21.62323454624631
21.72323454604611
21.82323454584591
21.92323454564571
222323454544551
22.12323454524531
22.22323454504511
22.32323454484491
22.42323454464471
22.52323344444450
22.62323344424430
22.72323344404410
22.82323344384390
22.92323344364370
232323344344350
23.12323344324330
23.22323344314320
23.32323344294300
23.42323344274280
23.52323344254260
23.62323344234240
23.72323344214220
23.82323344204210
23.92323344184190
242323344164170
24.12323344144150
24.22323344134140
24.32323344114120
24.42323344094100
24.52323344084090
24.62323344064070
24.72323344044050
24.82323344034040
24.92323344014020
252323343994000

A much better way of looking at this is using a graph. The green line shows the minimum number of sample counts possible for the narrowest '0' of 90us. The blue line shows the maximum number of sample counts possible for the widest '1' of 64us. When the two meet, the red line showing the difference in count falls to zero.

Zones of operation

In the graph above, the parts where the count is not zero are potential zones of operation. Starting from the right, the first zone of operation is the section between 21.4us and 22.4us. The next zone is 16.1us to 18us. The last zone is any period less than 15us.

To get the maximum period possible, the first zone is preferred. To get the maximum tolerance possible, the centre of the zone is used. This brings us to 21.9us - very close to the original period of 22us. The tolerance required is ±2%. This is within the specs for the PIC internal oscillator provided the temperature range is between 0° and 60°. At 21.9us and a 32MHz clock, the period represents 175 instructions. This is all the time you have to execute the ISR and still have cycles left over for the main routine to plod along.

The second zone will provide a bit more tolerance. The centre period for the 16.1us to 18us is 17us. The tolerance would be more than 5%. This is within the tolerance for the internal oscillator over the entire Vdd and temperature range. At 32MHz, the period represents 136 instructions.

Other Alternatives

A periodic interrupt is a viable alternative to precise coding. There are, however, other approaches. One is to use the change in input to trigger an interrupt. A timer can then be read to calculate the bit value. This will work well for accessory decoders as they get a clean signal without much noise. Mobile decoders using the rail for pickup will experience noise. This noise may affect the data received but, more importantly, repeated change of input requests could disrupt the decoding routine. An interrupt based approach may work better.

Disclaimer

I haven't tried this approach to DCC decoding. My layout is in the early stages. Most of my work is devoted to designing a command station. An accessory decoder is further down the track. It may use an interrupt based approach but will also have a crystal on board. When I get to signal decoders, which is way down the track, I will look at very low cost approaches using 8 pin PICs with internal 32 MHz clocks. The PIC12F1840 in an 8 pin PDIP or SOIC package with an internal oscillator of 32MHz, 6 I/O, 7K of program memory, 256 bytes of RAM, 256 bytes of EEPROM, 4 channel 10bit A/D for $2 is a good option.


No comments:

Post a Comment