-
-
Notifications
You must be signed in to change notification settings - Fork 111
What is DCC EX
WORK IN PROGRESS
DCC-EX is the software that runs in the command station CPU and generates the electrical signals to the track to power and control your locos and accessories. It converts commands from an external source (JMRI or throttles) into the track signals.
There are 4 essential building blocks to this, each designed to do a job well without worrying about the other layer issues :
-
A command input system and parser. (see code file DCCEXParser.cpp) This accepts all the input commands such as
<t 1 3 55 1>
(which means drive loco 3 at speed 55 forwards) and extracts the meaning and parameters from the text. It then calls the appropriate DCC function (e.gDCC::setThrottle(3,55,1);
-
The DCC packet layer. (see code file DCC.cpp) This provides functions such as setThrottle() or writeCV() to represent the various DCC operations that can be sent to the track. Each functions builds a DCC message (normally 3 or 5 bytes) which are in the formats laid down in the DCC standard. In addition this layer conrtains the steps necessary to manage complex DCC interactions such as those required to read CVs from locos on the programming track. Packets are passed to the next layer (Waveform) for transmission to the track. This layer is also responsible for remembering loco speed and function settings and periodically, in otherwise quiet times, retransmitting them to the track so that locos are reminded what they should be doing.
-
The DCC Waveform layer (see code file DCCWaveform.cpp) is responsible for creating the precisely timed digital signal to represent the packets it is asked to transmit. Each bit transmitted involves 2 changes of polarity for the track power and this happens every 58uS or 116uS depending on whether a zero or 1 bit is being sent. In addition packets must be prefixed by a number of 1 bits preamble, and then each byte of the packet is prefixed by an extra zero bit. Following the packet, a checksum byte is also transmitted. This layer operates on a continuous 58uS interrupt cycle and manages both the main and programming track signals simultaneously. If there are no packets to send then this sends IDLE packets to the main track or RESET packets to the program track. The requests to change the track polarity or power status are made by calling the MotorDriver layer.
Should this interrupt code be stopped at any time (perhaps by errant software blocking the interrupt system), the locos will see full power DC on the track and may run away at maximum speed, in an unpredictable direction, until they melt or hit something.
- The Motor Driver Layer (see code file MotorDriver.cpp) is responsible for communicating with the motor shield hardware in order to control the power and polarity of each track and checking the current for overloads. Each of the two tracks (main and programming) has a MotorDriver instance associated with it and each is configured with the Arduino pin numbers appropriate for the hardware you are using and the various factors necessary for converting current readings into milliamps. In this way, all the remainder of the command station is insulated from the need to understand the hardware configuration and it is possible to use different hardware combinations rather than just the standard shields.
In essence, the remainder of the code is for ancillary purposes (such as string formatting) or for optional features such as Wifi/Ethernet support, WitThrottle support, LCD/OLED displays and Turnouts/Outputs/Sensors but is not fundamental to the basic concept.
WIFI COMMUNICATION
The Wifi Communication feature is NOT suitable for layouts where you use a PC layout controller such as JMRI or RocRail. The Wifi communication feature is there to provide a simplified layout control option for those that wish to operate their layouts without the assistance of a PC or RasPi. It can not be used as a replacement for the USB connection.
****** SO IF YOU DONT NEED IT.. DONT WASTE TIME AND MONEY ON IT *****
To WiFi communication feature involved multiple complex building blocks.
-
The Configuration/Connection. (see code WifiSetup.cpp) This section detects the presence of the additional Wifi ESP chip or shield by polling the arduino Serial ports intil one of them responds to an AT command (The command language used to talk to the ES chip firmware.) having located the ES chip, tis code proceeds to configure the Wifi connection in Station Mode (connected to your home router) or Access Pont (AP) mode where the chip operates as a mini router. Further interactions establish the IP address or create an AP host name and password. Because this process takes place at Command Station startup, the process is permitted to make requests of the ES chip and actually wait to see the reply. a luxury not afforded to the remainder of the Wifi interaction!
-
The Wifi traffic interaction. (See code WifiInboundHandler.cpp) This layer operates in the arduino loop() phase, in other words it will be called frequently (many times a second) but it must NOT WAIT for anything otherwise the rest of the system will be blocked and nothing else will happen. The communication with the ES chip using the AT command language (citation needed) is far from simple and involves multiple complex exchanges of commands and responses which arrive in unpredictable sequence and time. This layer of code is responsible for juggling all these interactions, detecting and collecting incoming data traffic from connected clients, passing on incoming commands for execution, negotiating with the ES chip for the opportunity to send responses and dealing with clients that have disconnected. To do this, the inbound handler uses a Finite State Automation (FSA) to identify the meaning of each byte received from the ES. It must accumulate inbound commands in a buffer (code see RingBuffer.cpp) and passes completed input commands to the Command Distributor for processing. Results from the command are collected in another ring buffer and are transmitted back to the ES through a complex conversation that goes something like this:
- Are you busy? No!
- I would like to send 37 bytes to client 2. Hang on I'm Busy!
- Eh? I have 104 bytes from client 3 you must read first!
- Ok, let me have them. Here they are!
- Ok. Now you can send those bytes to client 2!
- here they are. BY the way client 1 disconnected!
- I would like to send 19 bytes to client 3. Your 37 bytes to client 2 just got sent!
and so on... The author would like to apologise for his slightly deranged mind... but that's what you get when you try to write code to handle this.
-
The Command Distributor (see code CommandDistributor.cpp) is merely responsible for checking the incoming command and determining whether its a
< >
like command to be passed to the Command parser, or a WiThrottle command which must be passed to the WiThrottle server. There is potential here for more command types should we choose to implement them. -
The WiThrottle server (see code WiThrottle.cpp) is a cut-down implementation of the Withrottle server normally found in JMRI. It is responsible for interpreting WiThrottle protocol commands (citation needed) and where necessary calling the DCC layer code described above to implement loco or accessory control operations.