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.
Period | Narrowest 1 | Widest 1 | Narrowest 0 | Widest 0 | Diff in Count | ||||
Min | Max | Min | Max | Min | Max | Min | Max |
10 | 5 | 6 | 6 | 7 | 9 | 10 | 1000 | 1001 | 2 |
10.1 | 5 | 6 | 6 | 7 | 8 | 9 | 990 | 991 | 1 |
10.2 | 5 | 6 | 6 | 7 | 8 | 9 | 980 | 981 | 1 |
10.3 | 5 | 6 | 6 | 7 | 8 | 9 | 970 | 971 | 1 |
10.4 | 5 | 6 | 6 | 7 | 8 | 9 | 961 | 962 | 1 |
10.5 | 4 | 5 | 6 | 7 | 8 | 9 | 952 | 953 | 1 |
10.6 | 4 | 5 | 6 | 7 | 8 | 9 | 943 | 944 | 1 |
10.7 | 4 | 5 | 5 | 6 | 8 | 9 | 934 | 935 | 2 |
10.8 | 4 | 5 | 5 | 6 | 8 | 9 | 925 | 926 | 2 |
10.9 | 4 | 5 | 5 | 6 | 8 | 9 | 917 | 918 | 2 |
11 | 4 | 5 | 5 | 6 | 8 | 9 | 909 | 910 | 2 |
11.1 | 4 | 5 | 5 | 6 | 8 | 9 | 900 | 901 | 2 |
11.2 | 4 | 5 | 5 | 6 | 8 | 9 | 892 | 893 | 2 |
11.3 | 4 | 5 | 5 | 6 | 7 | 8 | 884 | 885 | 1 |
11.4 | 4 | 5 | 5 | 6 | 7 | 8 | 877 | 878 | 1 |
11.5 | 4 | 5 | 5 | 6 | 7 | 8 | 869 | 870 | 1 |
11.6 | 4 | 5 | 5 | 6 | 7 | 8 | 862 | 863 | 1 |
11.7 | 4 | 5 | 5 | 6 | 7 | 8 | 854 | 855 | 1 |
11.8 | 4 | 5 | 5 | 6 | 7 | 8 | 847 | 848 | 1 |
11.9 | 4 | 5 | 5 | 6 | 7 | 8 | 840 | 841 | 1 |
12 | 4 | 5 | 5 | 6 | 7 | 8 | 833 | 834 | 1 |
12.1 | 4 | 5 | 5 | 6 | 7 | 8 | 826 | 827 | 1 |
12.2 | 4 | 5 | 5 | 6 | 7 | 8 | 819 | 820 | 1 |
12.3 | 4 | 5 | 5 | 6 | 7 | 8 | 813 | 814 | 1 |
12.4 | 4 | 5 | 5 | 6 | 7 | 8 | 806 | 807 | 1 |
12.5 | 4 | 5 | 5 | 6 | 7 | 8 | 800 | 801 | 1 |
12.6 | 4 | 5 | 5 | 6 | 7 | 8 | 793 | 794 | 1 |
12.7 | 4 | 5 | 5 | 6 | 7 | 8 | 787 | 788 | 1 |
12.8 | 4 | 5 | 5 | 6 | 7 | 8 | 781 | 782 | 1 |
12.9 | 4 | 5 | 4 | 5 | 6 | 7 | 775 | 776 | 1 |
13 | 4 | 5 | 4 | 5 | 6 | 7 | 769 | 770 | 1 |
13.1 | 3 | 4 | 4 | 5 | 6 | 7 | 763 | 764 | 1 |
13.2 | 3 | 4 | 4 | 5 | 6 | 7 | 757 | 758 | 1 |
13.3 | 3 | 4 | 4 | 5 | 6 | 7 | 751 | 752 | 1 |
13.4 | 3 | 4 | 4 | 5 | 6 | 7 | 746 | 747 | 1 |
13.5 | 3 | 4 | 4 | 5 | 6 | 7 | 740 | 741 | 1 |
13.6 | 3 | 4 | 4 | 5 | 6 | 7 | 735 | 736 | 1 |
13.7 | 3 | 4 | 4 | 5 | 6 | 7 | 729 | 730 | 1 |
13.8 | 3 | 4 | 4 | 5 | 6 | 7 | 724 | 725 | 1 |
13.9 | 3 | 4 | 4 | 5 | 6 | 7 | 719 | 720 | 1 |
14 | 3 | 4 | 4 | 5 | 6 | 7 | 714 | 715 | 1 |
14.1 | 3 | 4 | 4 | 5 | 6 | 7 | 709 | 710 | 1 |
14.2 | 3 | 4 | 4 | 5 | 6 | 7 | 704 | 705 | 1 |
14.3 | 3 | 4 | 4 | 5 | 6 | 7 | 699 | 700 | 1 |
14.4 | 3 | 4 | 4 | 5 | 6 | 7 | 694 | 695 | 1 |
14.5 | 3 | 4 | 4 | 5 | 6 | 7 | 689 | 690 | 1 |
14.6 | 3 | 4 | 4 | 5 | 6 | 7 | 684 | 685 | 1 |
14.7 | 3 | 4 | 4 | 5 | 6 | 7 | 680 | 681 | 1 |
14.8 | 3 | 4 | 4 | 5 | 6 | 7 | 675 | 676 | 1 |
14.9 | 3 | 4 | 4 | 5 | 6 | 7 | 671 | 672 | 1 |
15 | 3 | 4 | 4 | 5 | 6 | 7 | 666 | 667 | 1 |
15.1 | 3 | 4 | 4 | 5 | 5 | 6 | 662 | 663 | 0 |
15.2 | 3 | 4 | 4 | 5 | 5 | 6 | 657 | 658 | 0 |
15.3 | 3 | 4 | 4 | 5 | 5 | 6 | 653 | 654 | 0 |
15.4 | 3 | 4 | 4 | 5 | 5 | 6 | 649 | 650 | 0 |
15.5 | 3 | 4 | 4 | 5 | 5 | 6 | 645 | 646 | 0 |
15.6 | 3 | 4 | 4 | 5 | 5 | 6 | 641 | 642 | 0 |
15.7 | 3 | 4 | 4 | 5 | 5 | 6 | 636 | 637 | 0 |
15.8 | 3 | 4 | 4 | 5 | 5 | 6 | 632 | 633 | 0 |
15.9 | 3 | 4 | 4 | 5 | 5 | 6 | 628 | 629 | 0 |
16 | 3 | 4 | 4 | 5 | 5 | 6 | 625 | 626 | 0 |
16.1 | 3 | 4 | 3 | 4 | 5 | 6 | 621 | 622 | 1 |
16.2 | 3 | 4 | 3 | 4 | 5 | 6 | 617 | 618 | 1 |
16.3 | 3 | 4 | 3 | 4 | 5 | 6 | 613 | 614 | 1 |
16.4 | 3 | 4 | 3 | 4 | 5 | 6 | 609 | 610 | 1 |
16.5 | 3 | 4 | 3 | 4 | 5 | 6 | 606 | 607 | 1 |
16.6 | 3 | 4 | 3 | 4 | 5 | 6 | 602 | 603 | 1 |
16.7 | 3 | 4 | 3 | 4 | 5 | 6 | 598 | 599 | 1 |
16.8 | 3 | 4 | 3 | 4 | 5 | 6 | 595 | 596 | 1 |
16.9 | 3 | 4 | 3 | 4 | 5 | 6 | 591 | 592 | 1 |
17 | 3 | 4 | 3 | 4 | 5 | 6 | 588 | 589 | 1 |
17.1 | 3 | 4 | 3 | 4 | 5 | 6 | 584 | 585 | 1 |
17.2 | 3 | 4 | 3 | 4 | 5 | 6 | 581 | 582 | 1 |
17.3 | 3 | 4 | 3 | 4 | 5 | 6 | 578 | 579 | 1 |
17.4 | 2 | 3 | 3 | 4 | 5 | 6 | 574 | 575 | 1 |
17.5 | 2 | 3 | 3 | 4 | 5 | 6 | 571 | 572 | 1 |
17.6 | 2 | 3 | 3 | 4 | 5 | 6 | 568 | 569 | 1 |
17.7 | 2 | 3 | 3 | 4 | 5 | 6 | 564 | 565 | 1 |
17.8 | 2 | 3 | 3 | 4 | 5 | 6 | 561 | 562 | 1 |
17.9 | 2 | 3 | 3 | 4 | 5 | 6 | 558 | 559 | 1 |
18 | 2 | 3 | 3 | 4 | 5 | 6 | 555 | 556 | 1 |
18.1 | 2 | 3 | 3 | 4 | 4 | 5 | 552 | 553 | 0 |
18.2 | 2 | 3 | 3 | 4 | 4 | 5 | 549 | 550 | 0 |
18.3 | 2 | 3 | 3 | 4 | 4 | 5 | 546 | 547 | 0 |
18.4 | 2 | 3 | 3 | 4 | 4 | 5 | 543 | 544 | 0 |
18.5 | 2 | 3 | 3 | 4 | 4 | 5 | 540 | 541 | 0 |
18.6 | 2 | 3 | 3 | 4 | 4 | 5 | 537 | 538 | 0 |
18.7 | 2 | 3 | 3 | 4 | 4 | 5 | 534 | 535 | 0 |
18.8 | 2 | 3 | 3 | 4 | 4 | 5 | 531 | 532 | 0 |
18.9 | 2 | 3 | 3 | 4 | 4 | 5 | 529 | 530 | 0 |
19 | 2 | 3 | 3 | 4 | 4 | 5 | 526 | 527 | 0 |
19.1 | 2 | 3 | 3 | 4 | 4 | 5 | 523 | 524 | 0 |
19.2 | 2 | 3 | 3 | 4 | 4 | 5 | 520 | 521 | 0 |
19.3 | 2 | 3 | 3 | 4 | 4 | 5 | 518 | 519 | 0 |
19.4 | 2 | 3 | 3 | 4 | 4 | 5 | 515 | 516 | 0 |
19.5 | 2 | 3 | 3 | 4 | 4 | 5 | 512 | 513 | 0 |
19.6 | 2 | 3 | 3 | 4 | 4 | 5 | 510 | 511 | 0 |
19.7 | 2 | 3 | 3 | 4 | 4 | 5 | 507 | 508 | 0 |
19.8 | 2 | 3 | 3 | 4 | 4 | 5 | 505 | 506 | 0 |
19.9 | 2 | 3 | 3 | 4 | 4 | 5 | 502 | 503 | 0 |
20 | 2 | 3 | 3 | 4 | 4 | 5 | 499 | 500 | 0 |
20.1 | 2 | 3 | 3 | 4 | 4 | 5 | 497 | 498 | 0 |
20.2 | 2 | 3 | 3 | 4 | 4 | 5 | 495 | 496 | 0 |
20.3 | 2 | 3 | 3 | 4 | 4 | 5 | 492 | 493 | 0 |
20.4 | 2 | 3 | 3 | 4 | 4 | 5 | 490 | 491 | 0 |
20.5 | 2 | 3 | 3 | 4 | 4 | 5 | 487 | 488 | 0 |
20.6 | 2 | 3 | 3 | 4 | 4 | 5 | 485 | 486 | 0 |
20.7 | 2 | 3 | 3 | 4 | 4 | 5 | 483 | 484 | 0 |
20.8 | 2 | 3 | 3 | 4 | 4 | 5 | 480 | 481 | 0 |
20.9 | 2 | 3 | 3 | 4 | 4 | 5 | 478 | 479 | 0 |
21 | 2 | 3 | 3 | 4 | 4 | 5 | 476 | 477 | 0 |
21.1 | 2 | 3 | 3 | 4 | 4 | 5 | 473 | 474 | 0 |
21.2 | 2 | 3 | 3 | 4 | 4 | 5 | 471 | 472 | 0 |
21.3 | 2 | 3 | 3 | 4 | 4 | 5 | 469 | 470 | 0 |
21.4 | 2 | 3 | 2 | 3 | 4 | 5 | 467 | 468 | 1 |
21.5 | 2 | 3 | 2 | 3 | 4 | 5 | 465 | 466 | 1 |
21.6 | 2 | 3 | 2 | 3 | 4 | 5 | 462 | 463 | 1 |
21.7 | 2 | 3 | 2 | 3 | 4 | 5 | 460 | 461 | 1 |
21.8 | 2 | 3 | 2 | 3 | 4 | 5 | 458 | 459 | 1 |
21.9 | 2 | 3 | 2 | 3 | 4 | 5 | 456 | 457 | 1 |
22 | 2 | 3 | 2 | 3 | 4 | 5 | 454 | 455 | 1 |
22.1 | 2 | 3 | 2 | 3 | 4 | 5 | 452 | 453 | 1 |
22.2 | 2 | 3 | 2 | 3 | 4 | 5 | 450 | 451 | 1 |
22.3 | 2 | 3 | 2 | 3 | 4 | 5 | 448 | 449 | 1 |
22.4 | 2 | 3 | 2 | 3 | 4 | 5 | 446 | 447 | 1 |
22.5 | 2 | 3 | 2 | 3 | 3 | 4 | 444 | 445 | 0 |
22.6 | 2 | 3 | 2 | 3 | 3 | 4 | 442 | 443 | 0 |
22.7 | 2 | 3 | 2 | 3 | 3 | 4 | 440 | 441 | 0 |
22.8 | 2 | 3 | 2 | 3 | 3 | 4 | 438 | 439 | 0 |
22.9 | 2 | 3 | 2 | 3 | 3 | 4 | 436 | 437 | 0 |
23 | 2 | 3 | 2 | 3 | 3 | 4 | 434 | 435 | 0 |
23.1 | 2 | 3 | 2 | 3 | 3 | 4 | 432 | 433 | 0 |
23.2 | 2 | 3 | 2 | 3 | 3 | 4 | 431 | 432 | 0 |
23.3 | 2 | 3 | 2 | 3 | 3 | 4 | 429 | 430 | 0 |
23.4 | 2 | 3 | 2 | 3 | 3 | 4 | 427 | 428 | 0 |
23.5 | 2 | 3 | 2 | 3 | 3 | 4 | 425 | 426 | 0 |
23.6 | 2 | 3 | 2 | 3 | 3 | 4 | 423 | 424 | 0 |
23.7 | 2 | 3 | 2 | 3 | 3 | 4 | 421 | 422 | 0 |
23.8 | 2 | 3 | 2 | 3 | 3 | 4 | 420 | 421 | 0 |
23.9 | 2 | 3 | 2 | 3 | 3 | 4 | 418 | 419 | 0 |
24 | 2 | 3 | 2 | 3 | 3 | 4 | 416 | 417 | 0 |
24.1 | 2 | 3 | 2 | 3 | 3 | 4 | 414 | 415 | 0 |
24.2 | 2 | 3 | 2 | 3 | 3 | 4 | 413 | 414 | 0 |
24.3 | 2 | 3 | 2 | 3 | 3 | 4 | 411 | 412 | 0 |
24.4 | 2 | 3 | 2 | 3 | 3 | 4 | 409 | 410 | 0 |
24.5 | 2 | 3 | 2 | 3 | 3 | 4 | 408 | 409 | 0 |
24.6 | 2 | 3 | 2 | 3 | 3 | 4 | 406 | 407 | 0 |
24.7 | 2 | 3 | 2 | 3 | 3 | 4 | 404 | 405 | 0 |
24.8 | 2 | 3 | 2 | 3 | 3 | 4 | 403 | 404 | 0 |
24.9 | 2 | 3 | 2 | 3 | 3 | 4 | 401 | 402 | 0 |
25 | 2 | 3 | 2 | 3 | 3 | 4 | 399 | 400 | 0 |
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