Barnsley fern fractal

Thoughts on software architecture and development, and methods and techniques for improving the quality thereof.

David B. Robins (home)


Code Visions: Improving software quality
DCC operations mode address change

By David B. Robins tags: C++, Development, Trains Sunday, December 4, 2016 16:18 EST (link)

I've reorganized the ddcc code significantly to move even small but distinct parts of the code into their own modules with separate interfaces: the bit queue used to assemble DCC packets, the command parser, packets and packet factories (don't worry, I haven't gone full Javtard; they are just functions bundling parameters into a packet, or more precisely, a std::shared_ptr<Packet>). I had some responsiveness issues with the function (air horn) which I fixed, and idle is sending the last speed command. By default new commands are repeated 5x (should still be < 25 ms total) which works well.

Changing address proved a little tricky. Neither of the decoders I have will allow an immediate address change of the type in use, and I suspect that's general to mobile decoders; i.e., if it's currently using a short address you can't switch to another short address, and same for extended (a.k.a. 2-digit and 4-digit addresses). So address change sends a number of commands (all repeated individually 5x as noted above; even CV17-18 are not alternated).

First, I should note how I handle the two address types: I use a single space, and 0-127 (0 being broadcast) are short, 128+ are long, so "extended address 3" is represented by 128 + 3 = 131 internally. The largest extended address allowed is 0x27ff, which in my single space is 0x27ff + 128 = 0x287f. When I refer to addresses without prefixing "short" or "extended" assume a single-space address.

The sequence to change an address in operations mode (the alternate is "service mode" which is a broadcast and so requires either a separate track or removal of other locomotives from the track):

  1. set unused address type (CV #1 for short, CVs #17 and #18 for extended) to temporary address (127 for short, 0x287f for extended, i.e., CV #1 = 127 if the current address type is extended)
  2. switch address type (set bit 5 of CV #29 appropriately)
  3. set desired address type to new address (remember to send to the temp address!)
  4. switch address type (set bit 5 of CV #29 back to previous value)

Using the CV write-single-bit instruction to write CV #29 worked better for me than sending the whole byte. Of course, if the new address is of the opposite type to current, it's only necessary to set the unused type to new and flip bit 5 of CV #29.

I'm still not reading/verifying CVs. While the LMD18200 H-bridge does report current draw via a scaled current-sense output, the Raspberry Pi doesn't have an ADC. I may obtain an SPI ADC IC like the MCP3008 to do this. (The circuit will also need a resistor to convert microamps to volts.)

Content on this site is licensed under a Creative Commons Attribution 3.0 License and is copyrighted by the authors.