The goal of the USB to DCC project is to create a DCC booster that is interfaced with a PC through USB. We want to switch from the serial and parallel ports to USB for the following reasons:
In addition to supporting DCC signaling from the PC to the layout, this project will create an interface with the Loconet bus.
The firmware has to handle the following tasks:
A typical USB firmware can be divided into two parts: handling of the enumeration and other required standard activities and handling of the application specific data (payload). The standard part being handled by a micro controller manufacturer in the form of a library or code sample, we will not describe it here.
This device is classified by the USB specification as "full speed". This means that the device can send or receive bursts of data at up 12Mb/s.
The DCC and Loconet functions will be accessed through two separate pairs of endpoints. From a PC operating system's point of view, the two functions will look like two independant devices.
The device will use bulk type transfers.
The input endpoint will initialy have a very limited use (curently, DCC is a mostly one way communication protocol but a new, bidirectional protocol is coming). The structure of a report will be:
|Byte 0, bit 7||Set if this packet is an acknowledge from a programming command||PROG_ACK|
|Byte 0, bit 6||Set if this packet is a response from a booster command||COMM_ACK|
|Byte 0, bits 5 to 3||Reserved, ignore for future compatibility|
|Byte 0, bits 2 to 0||Number of local throttles present||NUM_LOCAL_THROTTLES|
|Byte 1||Packet number of the command being acknowledged.||PACKET_NUM_ACK|
|Byte 2, bit 7||Local throttle 1, direction||LOCAL_DIR_1|
|Byte 2, bits 6 to 0||Local throttle 1, speed||LOCAL_SPEED_1|
|Byte 3, bit 7||Local throttle 2, direction||LOCAL_DIR_2|
|Byte 3, bits 6 to 0||Local throttle 2, speed||LOCAL_SPEED_2|
|Byte 4, bit 7||Local throttle 3, direction||LOCAL_DIR_3|
|Byte 4, bits 6 to 0||Local throttle 3, speed||LOCAL_SPEED_3|
|Byte 5, bit 7||Local throttle 4, direction||LOCAL_DIR_4|
|Byte 5, bits 6 to 0||Local throttle 4, speed||LOCAL_SPEED_4|
|Byte 6, bits 7 and 6||Local throttle 4, special functions||LOCAL_SPECIAL_4|
|Byte 6, bits 5 and 4||Local throttle 3, special functions||LOCAL_SPECIAL_3|
|Byte 6, bits 3 and 2||Local throttle 2, special functions||LOCAL_SPECIAL_2|
|Byte 6, bits 1 and 0||Local throttle 1, special functions||LOCAL_SPECIAL_1|
Please note that throttle implementation is optional.
The packet's format is shown in the following table.
|Byte and bit number||Use||Name|
|Byte 0, bits 0, 1 and 2||Number of DCC bytes, including address||NUM_DCC_BYTES|
|Byte 0, bit 3||Set if extended sync field, cleared if normal sync field||EXT_SYNC|
|Byte 0, bit 4||Set if the packet is to be sent to the layout, cleared if the packet is to sent to the programming track||LAYOUT_PACKET|
|Byte 0, bits 5 to 7||Packet number||PACKET_NUM|
|Byte 1||DCC address||DCC_ADDR|
|Bytes 2, 3, 4, 5||DCC data||DCC_DATA[0..3]|
|Byte 7||Booster state control||BOOST_CTRL|
|0||Main track power||B_MAIN_PWR|
|1||Programming track power||B_PROG_PWR|
The other bits are reserved and must be zero.
A basic DCC packet has the following structure:
|Preamble||Address (one byte)||Field separator (one bit at 0)||Data (one byte)||Field separator (one bit at 0)||Checksum (one byte)||End of packet (one bit at one)|
Extended packets have up to 4 data bytes, each one separated from the next by a single bit at zero. For more details on this subject, see the standard on the NMRA website
The details of the signaling used by DCC is clearly shown on the NMRA website. This type of signal can be generated either by using a simple timer with an interrupt (very time consuming option, as each bit creates two interrupts) or with a timer setup as PWM or single pulse generator. A third option would be to use a serial port (UART), sending the caracter 0x0F at two different speeds.
Reguardless of the peripheral used, care must be taken to insure that the booster output will never "get stuck" at one or zero. This means that interrupt response time must be kept short.
Currently two platforms are targeted: Linux and MS Windows. As mentionned previously, our physical device will appear as two logical device on the host system. As a result, the applications for DCC and Loconet can be completely separate from each other. Because of the muli-platform environement, the code needs to be portable and modular. As a result, the application code will be written in C++ and the GUI will be based on a portable tool kit such as WxWindows.
All user level code will be portable. In addition, we are planing to use Libusb (the Linux version has been ported to MS Windows.) to access the physical device. The code will be broken down into several modules. Each module is a C++ class with a set of methods accessible from the other modules. These methods will act on other objects described below.
The following modules are currently planned:
The following objects will be accessed by the various modules: