Using the RailDriver with Dovetail TS

Required Components for the RailDriver to work with Dovetail TS:

•RailDriver unit - calibrated. If your unit has not been calibrated it can be calibrated at any time following the instructions under the Calibrate section below.
•MacroWorks 3.1 for RailDriver installed, version 1.1.1.73 or higher. Download.
•Dovetail TS installed (via Steam). This will install RailDriver.dll which should be located in C:\Program Files (x86)\Steam\steamapps\common \railworks\plugins

Get Driving:

1. Start up Dovetail TS, pick desired loco and route.
2. Plug in RailDriver to available USB port

3. Start MacroWorks 3.1. When MacroWorks 3.1 launches for the first time, it will ask you to calibrate. Follow the instructions through the calibration utility. If you wish to recalibrate follow the instructions under the Calibrate section. You must restart MacroWorks 3.1 after recalibrating.
4. In MacroWorks 3.1, go to File -> New. Note: this step needs to be done only once. Once the template script is loaded the working script is created from it and stored in the user's directory C:\Users\UserName\AppData\Local\PI Engineering\MacroWorks 3\MyScripts\RailDriver with the name Script_210_XX.mw3. Advanced users may wish to modify this script per instructions below.
5. Return focus to the Train Simulator and start driving. It does not really matter if you get Dovetail TS running first or MacroWorks 3.1, as long as both are running eventually.

Calibrate:

If your unit has not been calibrated or you wish to recalibrate it. Browse to the directory C:\Program Files (x86)\PI Engineering\MacroWorks 3.1\Devices\RailDriver\RD Calibration and start up RDcalibration.exe. Follow the onscreen steps. After calibrating you must restart MacroWorks 3.1.

Details for Advanced Users:

The RailDriver controls are mapped to available loco controls from the Control List Dialog. To see all of the available controls and their values for the selected loco show the Control List Dialog. In Steam right click on Train Simulator 20XX, select Properties and click Set Launch Options. Type -ShowControlStateDialog and OK. Run game in windowed mode. In the main game screen in the upper right corner click Settings -Graphics and change Full Screen to Windowed.

As the train is driven or manipulated using the onscreen controls, the equivalent values change accordingly in the Control List Dialog. The script maps some of these controls to the RailDriver by use of the RailDriver.dll. This dll, written by Dovetail TS, allows the script to read and write the values of the controls. The script continuously checks to see of the loco has changed in timer1_Tick subroutine of the Script_210_XX.mw3. If the loco changes all of the control IDs are reassigned and new translations for the analog levers are determined in CalculateTranslations subroutine.

If you feel the RailDriver is not behaving as expected first check to see that the onscreen controls are also behaving in the same way. Exit MacroWorks 3.1. This removes the RailDriver from controlling anything in the game. Now using the mouse and/or keyboard change the control of interest using the game control. If it behaves the same way then the RailDriver is doing what it is supposed to be doing and the culprit is most likely a situation you are not familar with. If it does not behave the same then there could be an issue with the RailDriver. Most common issues involve mapping the control to the wrong control ID.

The following controls are mapped to the RailDriver analog levers/switches in the following priorities, if the top control is missing then the next one down is used and so on.

Reverser lever:
UserVirtualReverser
VirtualReverser
Reverser

Throttle section of the combined throttle and dynamic brake lever*:
VirtualThrottle
ThrottleAndBrake
Regulator
SimpleThrottle

Dynamic section of the combined throttle and dynamic brake lever*:
VirtualDynamicBrake
DynamicBrake

Train/auto brake lever:
VirtualBrake
TrainBrakeControl

Upper detent of the train/auto brake lever:
EmergencyBrake

Engine/loco brake lever:
VirtualEngineBrakeControl
EngineBrakeControl

Wipers**:
VirtualWipers
Wipers

Headlights:
VirtualHeadlights
Headlights

LED display:
SpeedometerMPH or SpeedometerKPH

*The combination of controls determines the variable ThrottleStyle in the script; 0, 1 or 2. There is also available ThrottleStyle=3 which forces the lever to be all throttle. To use this the ThrottleStyle must be manually set to 3 in the script which can be done by uncommenting (remove the REM) the line 1568 in CalculateTranslations subroutine of Script_210_XX.mw3. REM ThrottleStyle=3 'forces the dynamic brake/throttle lever to be all throttle for entire lever range

**Currently the upper rotary switch is using keyboard v to control the wipers, where position 1 is off and the other 2 positions are on. If wipers get out of sequence type a v on the keyboard.

In order for the script to properly map a control to a lever it needs to know its minimum and maximum limits within the game. The RailDriver.dll provides these via the GetControllerValue function. For advanced users and developers may wish to hardcode the minimum and maximum values into the script. An example of this method can be found in the script around lines 1582-1589 in CalculateTranslations subroutine. It checks if the loco is the Class801 and if so then reassigns the minimum and maximum variables for the combined throttle and brake. Note for the combined throttle and brake the RailSimCombinedThrottleBrakeN must be recomputed using the new minimums and maximums if changed! For other controls only the minium and maximum variables need to be reassigned. But how does one know the loco name and the minimums and maximums? The minimum and maximum values are obtained by moving the control, using on screen methods (not the RailDriver), to its limits and noting the values in the Control List Dialog. The loco name can be obtained using the Train Simulator RailDriver.dll Sample written by P.I. Engineering or from tech support. With Train Simulator running with a loco start TrainSim_RailDriverdll_Sample.exe. Click GetLocoName and a string in the form of PROVIDER.:.PRODUCT.:.ENGINENAME will show up. If nothing is returned click SetRailDriverConnected and try again. So the loco name (ENGINENAME) string is known. There may be a way to get this name from the game itself but I have not found out how.

RailDriver.dll API Reference:

void SetRailDriverConnected(boolean Connected)

Connect or disconnect the dll to the Dovetail TS app.

string GetLocoName()

This function returns the Provider, Product and Engine name of the engine being driven at the moment. This is in the form “PROVIDER.:.PRODUCT.:.ENGINENAME”. This allows application developers to accurately determine what locomotive is being driven and adapt accordingly.

string GetControllerList()

This function returns a list of every controller in the current locomotive. Each one is separated by two colons (::). This list is later used for indexing so the first entry in this list should be considered controller 0 and the next controller 1 etc. This is something like “Alerter::VirtualThrottle::Regulator::TrainBrake” etc. This would usually be the same list as seen in the Control State Dialog.

float GetControllerValue(int controllerId, int getType)

This function queries the value of a controller and returns it. getType should be 0 to get the current value, 1 to get the minimum value of this controller and 2 to get the maximum value of this controller. It is important to use the controllerId within the context of the values returned by GetControllerList as it cannot be assumed that a particular controller is always at the same ID on different loco’s, in fact it quite often won’t be.

void SetControllerValue(int controllerId, float value)

Set the new current value of the controller specified to the value provided.

In addition to the controllers that are returned via GetControllerList() there are some additional “virtual” controllers that are provided by the EI itself, these are:

Controller ID Purpose
400 Latitude of Train
401 Longitude of Train
402 Fuel Level
403 Is in a Tunnel?
404 Gradient
405 Heading
406 Time of day hours
407 Time of day minutes
408 Time of day seconds

Implementation Guide

It is expected that applications will frequently call GetLocoName to determine if the locomotive has changed. If it does change, then the application should call GetControllerList and then determine if it needs to adjust how it’s interacting with the current locomotive.

If the application is trying to be more generic in how it interacts with different types of locomotives, it may be important to call the GetControllerValue function on initialisation to request the Min and Max of each controller that the application might want to set – this would then allow the application to scale its values from 0 to 100% accordingly, rather than assuming that all controls are perhaps 0.0 to 1.0 (which maybe the case generally but will leave edge cases not working).

Operationally, the application would then use the GetControllerValue to retrieve values and SetControllerValue to set them. Note that note all controllers can have their values set – the same rules as for LUA Engine scripts apply (e.g. you can’t set the boiler pressure). All controls can be read from.