How your game software should connect to the NET processor¶
If you're writing your own game software, this guide explains how it should connect to the NET processor, including examples of commands to send and the order they should be sent.
From a high-level, the steps are:
- Figure out which port the NET processor is
- Clear out the serial buffers
- Send an
- Configure the hardware with the
- Expire the watchdog
- Query the I/O boards
- Get the initial switch states
- Configure all the drivers
- Configure all the switches
- Start the watchdog timer
By this point you'll be ready to start the attract mode, and then to start the game.
Figuring out which port the NET connection is¶
When you connect a FAST Pinball controller to your computer, several serial ports should automatically appear. No driver installation is necessary. Your game software will obviously need to know which ports are which.
FAST Pinball platform controllers identify themselves with USB Vendor ID
0x2E8A and Product ID
0x103B. This is the Raspberry Pi Foundation's VID (we use the RP2040 processor for USB communications), with a FAST Pinball assigned PID. The exception is the Nano, which uses an FTDI USB chip. It is not necessary to query this or even to care what the PID/VID is, but the option exists if you want it.
Or you can just look for the port names which appear when the Neuron is connected and powered on. (Check out the Neuron initial connection tutorial to understand the board and connecting to its ports.)
In MPF, the config files specify which connections use which ports, so MPF doesn't "look for" hardware at all, it just uses whatever port is in the config file. But you could definitely use the VID/PID technique to do an auto-detection of the hardware.
Three serial ports will appear with the latest (
-5 hardware revision) Neuron controllers. In most cases, the first port (lowest number) will be the NET processor connection, though on Windows the order could be random. (Because Windows?) You must connect at 921600, 8N1.
Clear out the serial buffers¶
Once you make the actual serial connection, the next step should be to clear out any random junk in the serial buffers. You can send a few random bytes; something like several CRs or spaces. The Neuron will respond with
XX:F for invalid commands it receives, so you can pretty much just send a few random bytes until you get the
XX:F message back.
CR = Carriage Return
In this guide, we'll use the term "CR" to mean Carriage Return. This is the ASCII character
0x0D, often times escaped as
When MPF first connects to the port it thinks the NET processor is on, it sends 1024 space characters, followed by a CR. This causes the Neuron to respond as
XX:F which is how MPF knows the serial buffers and random stuff is cleared out.
Sometimes whatever random junk or noise that's in the serial buffers is not valid UTF-8 characters which causes UTF-8 decoding to fail. MPF ignores decode errors until the first
XX:F comes through. Then we know there's a solid connection, and from that point on, UTF-8 decode errors raise exceptions.
Send an ID:¶
Once the serial connection is established, you next probably want to send an
ID: command and await the response. This will return a string with the hardware revision, serial number, and other information. You can use this to confirm that you're talking to the right port, and that the hardware is what you expect and a supported firmware level, and that you have a proper communication channel with the hardware.
>>>> ID: ID:NET FP-CPU-2000 02.13
Note that the model number does not include the trailing dash. (e.g. the model number printed on the current Neurons is
FP-EXP-2000-5) The final number is the hardware revision number, which is transparent to the firmware. The firmware doesn't know what hardware revision number it's running on.
At the time of this writing
2.13 is the latest firmware for the Neuron, though firmware
2.06 or newer is fine. The Retro Controllers use the same firmware as the Neuron, so firmware
2.13 have changes for the Retro Controllers.
Configure hardware with CH:¶
Before any commands apart from
ID: will work, you must send a
CH: command to configure the hardware. This tells the firmware on the board what type of hardware it has, as well as configures options for how switches are read. For a Neuron, you would send
CH:2000,01 to tell the board that it's a Neuron and that you want switch state changes to be reported asynchronously. (The
01 is the switch state change reporting mode.)
>>>> CH:2000,01 CH:P
MPF waits for this command response before proceeding.
Note that if you skip this step, the watchdog command and pretty much everything else will not work. The firmware will not know what hardware it has, and will not know how to read switches, so it will not be able to respond to any commands.
Expire the watchdog¶
Once you know you're connected to the right port, you should send
WD:1 to force expire the watchdog timer. (This technically expires the watchdog in 1ms.) The reason for this is who knows what state the controller was in before you connected? Maybe someone was playing around and set the watchdog for a really long time, and maybe drivers are active, or?? So just expire it so you know you're starting from a known state.
>>>> WD:1 WD:P
Remember everything is HEX!
All numbers and values in the FAST Serial Protocol are two bytes of hex. Expiring the watchdog in 10ms would be
WD:0A. Expiring it in 100ms would be
Some people have asked if they can just expire the watchdog during tilt and game end as an easy way to shut everything down. We don't like that technique, with details explained in the Watchdog WD: command reference.
No need to reboot the controller¶
BR: is used to reboot the Neuron. It is not necessary to do this on startup, or really at all during standard operation. If you do choose to reboot the Neuron, it will take about 1.5 seconds. The host computer will receive a
!B:00 message when the Neuron first starts rebooting, and then a
!B:02 message when it's ready. There will also be some other junk / non complete messages as the hardware electrical states change as things reboot.
Even if you don't reboot the Neuron, your game framework should be ready to receive
!B commands and handle them appropriately.
Query the node boards (I/O boards)¶
Now that you know you're connected to a Neuron, the next step is to find out what I/O boards are connected. You can do this with the
NN: command queries the node boards (I/O boards) connected to the Neuron. You can use this to find out how many boards are connected, what type they are (count of switches and drivers), and the firmware.
NN: command is designed to be used with a board address. You can start with
NN:00, wait for the response, and then increment the address until you get a response that indicates the node board is not found.
Verifying the firmware version is probably not important, but also fine to do. The Neuron controller will obviously not connect to a node board with firmware that's not compatible, so by definition, if you have a node board connected, it's firmware is compatible.
MPF config files specify the order of the I/O boards in the loop. So if it sees that the boards are not in the same order of the config, it will raise an exception (since board order affect switch and driver numbers, and it's easy when you're messing around to plug the boards together in the wrong order).
If you only have one of each board type, you could even make your software automatically adjust the switch and driver numbers based on the actual order of the board.
Or you could just ignore the order and know it's important to connect them in the right order. If you're writing your own game software for a homebrew that just you will maintain, this is probably fine.
Get the initial switch states¶
Next you can use the
SA: command or
SD: command to query the switch states. (The
SA: is an ASCII command and the
SD: is the binary version. Both of these return a string of bits which corresponds to the current debounced hardware state of all switches. You can use this to initialize your switch state tracking.
Using ASCII versus binary probably doesn't matter here, since this command is only occasionally used and easy enough to parse either way, so use whichever is easier for you. MPF uses
On the Neuron, these commands will always report having 104 switches (command byte length
0x0E), so just use this command to get the state of the switches, knowing how many you have from the
Also note that these commands report the raw hardware state of the switches. If you invert the reporting of a switch with the
SL: command later, the
SA: results don't change.
It's probably not necessary to use this command during a game or throughout the machine's lifecycle. Some people like to do this when a game ends, just to check and verify things, but if this command reveals that a switch is not in the state you expected, then you probably have bigger issues. (Like, where did the
-L: commands go?)
Old school pinball code (like the WPC code in the 90s) constantly queried the switches instead of receiving asynchronous notifications of switch changes. So if you're emulating something like that, you can use the
CH: command to configure the Neuron to NOT send notifications of switch changes, and instead you can use the
SD: command to poll the switch states. (This is not recommended, but it's technically possible.)
Send the initial driver configurations¶
Next, use the
DL: command to configure all of your drivers. You should set the state for all drivers on every board that's connected, even if they're not used in your game. (Just use Trigger
00 and Mode
00 for the unused drivers.)
We like to send the
DL: commands one-by-one and await the
DL:P responses. The full round trip should be pretty quick, 10-30ms (depends on serial buffer flush configuration and timing). Older versions of MPF would send all the commands at once, count how many went out, count how many
DL:P responses came back, and try to wait and keep everything in sync. But there wasn't really any value in that, and it was complicated, so now MPF sends configuration commands one at a time and waits for the
DL:P response before sending the next one. You only need to do this when the machine starts up, not every time you start a game, and the whole process typically takes around 500ms even doing them one-by-one.
At this point you're just configuring the driver settings (how they're pulsed or fired, the ID of any associated switches, etc.). For manually controlled drivers (ball ejects, target resets, motors or magnets, etc.), you can fully "enable" them now since they don't actually fire until you send a
TL: command anyway.
DL:xx,81,xx,xx,... # Configure driver for manual control later
DL: command above uses trigger option
81 which means the driver is enabled (
01) and manually controlled (
xx values are not relevant for this portion of the documentation, but would be your driver ID, switch ID, driver mode, etc.
Then when you want to actually fire the driver later, or if you want to configure the driver to be an autofire hardware driver (e.g. enable the flippers on game start), you would send a
When MPF sends
TL: commands, it does them in bulk. (Well, since these are for the autofires only, you probably only have 8-10 for the entire machine.)
TL: commands are processed faster by the Neuron (since it's just modifying bits in existing driver objects that were already configured via
DL:), so sending them in bulk is fine. MPF ignores
We have specific guides for each type of pinball device which show the exact
TL: commands you would use for each type of device. Refer to that documentation for the specifics of what exact commands, triggers, and driver modes to use for flippers, pop bumpers, etc.
Next, use the
SL: command to configure all of your switches. Again, we like to do this one-by-one and await the
SL:P responses, and again, this only needs to happen when the machine is starting up, not every game.
See our guidance for switch programming for examples and details.
Start the watchdog timer¶
Now that the hardware is initialized, you can start the watchdog timer again. We typically recommend that you refresh the timer at half the timeout period. So if you set the watchdog timeout to 1 second, you should refresh it every 500ms. (This is just a recommendation, you can do whatever you want.) Here's an example command you'd send every 500ms to set the watchdog timer to 1 second (1000ms,
>>>> WD:3E8 WD:P
You will get
WD:P messages back, which you can probably ignore. MPF ignores them.
Modifying & changing drivers as the game progresses¶
The sections below explain the general concepts of how you enable, disable, and change device configurations, but you should refer to the device programming documentation for the exact commands and settings you should use for each type of device.
Enabling things when the game starts¶
When the game starts, you'll want to enable autofire trigger rules for drivers that have them using
TL: commands. You only need to run this for your autofire drivers, not the manually-activated drivers. So this is just for your flippers, slingshots, pop bumpers, etc.
See the device guidance for specifics.
Disabling things when the game ends¶
When the game ends, or when you otherwise want to disable autofire devices (like during tilt), you can also use
TL: commands for each autofire driver.
You don't need to disable the manually-activated drivers, since they aren't going to fire on their own. Plus you might need them even when a player isn't active. For example, you need to be able to eject balls that land in things as they're draining during tilt, and often times you'll need to move balls around during attract mode. So just leave those enabled and only worry about your autofires.
Again, see the device guidance for specifics.
Manually pulsing an autofire driver¶
Sometimes you need to take manual control of a driver that's configured for autofire. For example, you might need to fire a pop bumper during ball search, or manually pulse a flipper during a flipper novelty mode. In that case, you can use a
TL: command to one-shot "tap" the driver:
See the device guidance for specifics.
Reconfiguring drivers during game play¶
Most driver interactions during game play can be done with
TL: commands, because really all you're doing is changing how the driver is fired (triggered), not changing core configuration. (This trigger change works in several directions: manually controlled drivers are manually triggered to fire, autofire drivers are have their autofire switch trigger rules disabled or enabled, etc.)
So the vast majority of driver interactions during game play can be done with
TL: commands. However, there are some cases where you need to change the core configuration of a driver, like if you are implementing a flipper novelty mode, or if the operator changes a pulse setting via the service menu.
In that case, sending a
DL: command is the way to go. Doing this will completely kill and replace the driver object, and again we like to send those commands one-by-one and await the responses.
Example NET serial protocol command sequence¶
Here's the serial command log of MPF starting up and connecting to the Neuron's NET port.
>>>>are raw commands from the host PC to the EXP connection
<<<<are raw messages from the EXP connection to the host PC
- Since this log is raw serial chunks, you'll see messages are often received in chunks.
- Click the (+) for details on a specific line.
14:49:53,714 : [NET] : Connected to /dev/tty.usbserial-14301 at 921600bps 14:49:53,714 : [NET] : >>>> ' ' 14:49:53,714 : [NET] : >>>> '\r' # (1)! 14:49:53,742 : [NET] : <<<< 'XX:F\r' 14:49:53,743 : [NET] : >>>> 'ID:\r' 14:49:53,758 : [NET] : <<<< 'ID:NET FP-CPU-2000 02.13\r' 14:49:53,759 : [NET] : >>>> 'CH:2000,FF\r' 14:49:53,774 : [NET] : <<<< 'CH:P\r' 14:49:53,775 : [NET] : >>>> 'WD:1\r' 14:49:53,775 : [NET] : >>>> 'NN:00\r' 14:49:53,790 : [NET] : <<<< 'WD:P\rNN:00,FP-I/O-1604-3 ,01.09,04,10,00,00,00,00,00,00\r' 14:49:53,791 : [NET] : >>>> 'NN:01\r' 14:49:53,806 : [NET] : <<<< 'NN:01,FP-I/O-0804-3 ,01.09,04,08,00,00,00,00,00,00\r' 14:49:53,807 : [NET] : >>>> 'NN:02\r' 14:49:53,822 : [NET] : <<<< 'NN:02,FP-I/O-1616-3 ,01.09,10,10,00,00,00,00,00,00\r' 14:49:53,824 : [NET] : >>>> 'NN:03\r' 14:49:53,838 : [NET] : <<<< 'NN:03,FP-I/O-3208-3 ,01.09,08,20,00,00,00,00,00,00\r' 14:49:53,839 : [NET] : >>>> 'SA:\r' 14:49:53,854 : [NET] : <<<< 'SA:0E,00107C00773F0001000000000000\r' 14:49:54,150 : [NET] : >>>> 'DL:00,00,00,00\r' 14:49:54,158 : [NET] : <<<< 'DL:P\r' 14:49:54,358 : [NET] : >>>> 'DL:04,00,00,00\r' 14:49:58,145 : [NET] : <<<< 'DL:P\r' 14:49:58,147 : [NET] : >>>> 'DL:07,00,00,00\r' 14:49:58,163 : [NET] : <<<< 'DL:P\r' 14:49:58,165 : [NET] : >>>> 'DL:06,00,00,00\r' 14:49:58,226 : [NET] : <<<< 'DL:P\r' 14:49:58,227 : [NET] : >>>> 'DL:05,00,00,00\r' 14:49:58,237 : [NET] : <<<< 'DL:P\r' 14:49:58,238 : [NET] : >>>> 'DL:08,00,00,00\r' 14:49:58,254 : [NET] : <<<< 'DL:P\r' 14:49:58,254 : [NET] : >>>> 'DL:09,00,00,00\r' 14:49:58,272 : [NET] : <<<< 'DL:P\r' 14:49:58,272 : [NET] : >>>> 'DL:0A,00,00,00\r' 14:49:58,286 : [NET] : <<<< 'DL:P\r' 14:49:58,287 : [NET] : >>>> 'DL:0B,00,00,00\r' 14:49:58,302 : [NET] : <<<< 'DL:P\r' 14:49:58,303 : [NET] : >>>> 'DL:0D,00,00,00\r' 14:49:58,318 : [NET] : <<<< 'DL:P\r' 14:49:58,318 : [NET] : >>>> 'DL:0C,00,00,00\r' 14:49:58,334 : [NET] : <<<< 'DL:P\r' 14:49:58,335 : [NET] : >>>> 'DL:10,00,00,00\r' 14:49:58,350 : [NET] : <<<< 'DL:P\r' 14:49:58,351 : [NET] : >>>> 'DL:13,00,00,00\r' 14:49:58,366 : [NET] : <<<< 'DL:P\r' 14:49:58,367 : [NET] : >>>> 'DL:12,00,00,00\r' 14:49:58,382 : [NET] : <<<< 'DL:P\r' 14:49:58,382 : [NET] : >>>> 'DL:11,00,00,00\r' 14:49:58,398 : [NET] : <<<< 'DL:P\r' 14:49:58,399 : [NET] : >>>> 'DL:14,00,00,00\r' 14:49:58,414 : [NET] : <<<< 'DL:P\r' 14:49:58,414 : [NET] : >>>> 'DL:18,00,00,00\r' 14:49:58,430 : [NET] : <<<< 'DL:P\r' 14:49:58,430 : [NET] : >>>> 'DL:19,00,00,00\r' 14:49:58,449 : [NET] : <<<< 'DL:P\r' 14:49:58,450 : [NET] : >>>> 'DL:1A,00,00,00\r' 14:49:58,462 : [NET] : <<<< 'DL:P\r' 14:49:58,463 : [NET] : >>>> 'DL:1B,00,00,00\r' 14:49:58,478 : [NET] : <<<< 'DL:P\r' 14:49:58,478 : [NET] : >>>> 'DL:1C,00,00,00\r' 14:49:58,494 : [NET] : <<<< 'DL:P\r' 14:49:58,495 : [NET] : >>>> 'DL:1D,00,00,00\r' 14:49:58,510 : [NET] : <<<< 'DL:P\r' 14:49:58,510 : [NET] : >>>> 'DL:1E,00,00,00\r' 14:49:58,526 : [NET] : <<<< 'DL:P\r' 14:49:58,526 : [NET] : >>>> 'DL:1F,00,00,00\r' 14:49:58,542 : [NET] : <<<< 'DL:P\r' 14:49:58,543 : [NET] : >>>> 'SL:00,01,04,04\r' 14:49:58,558 : [NET] : <<<< 'SL:P\r' 14:49:58,559 : [NET] : >>>> 'SL:01,01,04,04\r' 14:49:58,574 : [NET] : <<<< 'SL:P\r' 14:49:58,575 : [NET] : >>>> 'SL:02,01,04,04\r' 14:49:58,590 : [NET] : <<<< 'SL:P\r' 14:49:58,591 : [NET] : >>>> 'SL:03,01,04,04\r' 14:49:58,606 : [NET] : <<<< 'SL:P\r' 14:49:58,606 : [NET] : >>>> 'SL:04,01,04,04\r' 14:49:58,622 : [NET] : <<<< 'SL:P\r' 14:49:58,623 : [NET] : >>>> 'SL:06,01,04,04\r' 14:49:58,638 : [NET] : <<<< 'SL:P\r' 14:49:58,638 : [NET] : >>>> 'SL:05,01,04,04\r' 14:49:58,654 : [NET] : <<<< 'SL:P\r' 14:49:58,654 : [NET] : >>>> 'SL:07,01,04,04\r' 14:49:58,671 : [NET] : <<<< 'SL:P\r' 14:49:58,672 : [NET] : >>>> 'SL:08,01,04,04\r' 14:49:58,686 : [NET] : <<<< 'SL:P\r' 14:49:58,687 : [NET] : >>>> 'SL:09,01,04,04\r' 14:49:58,702 : [NET] : <<<< 'SL:P\r' 14:49:58,703 : [NET] : >>>> 'SL:0A,01,04,04\r' 14:49:58,718 : [NET] : <<<< 'SL:P\r' 14:49:58,718 : [NET] : >>>> 'SL:0B,01,04,04\r' 14:49:58,734 : [NET] : <<<< 'SL:P\r' 14:49:58,734 : [NET] : >>>> 'SL:0C,01,04,04\r' 14:49:58,750 : [NET] : <<<< 'SL:P\r' 14:49:58,751 : [NET] : >>>> 'SL:10,01,04,04\r' 14:49:58,766 : [NET] : <<<< 'SL:P\r' 14:49:58,766 : [NET] : >>>> 'SL:11,01,04,04\r' 14:49:58,782 : [NET] : <<<< 'SL:P\r' 14:49:58,783 : [NET] : >>>> 'SL:12,01,04,04\r' 14:49:58,798 : [NET] : <<<< 'SL:P\r' 14:49:58,798 : [NET] : >>>> 'SL:13,01,04,04\r' 14:49:58,814 : [NET] : <<<< 'SL:P\r' 14:49:58,815 : [NET] : >>>> 'SL:14,01,04,04\r' 14:49:58,830 : [NET] : <<<< 'SL:P\r' 14:49:58,830 : [NET] : >>>> 'SL:15,01,04,04\r' 14:49:58,849 : [NET] : <<<< 'SL:P\r' 14:49:58,849 : [NET] : >>>> 'SL:16,01,04,04\r' 14:49:58,862 : [NET] : <<<< 'SL:P\r' 14:49:58,863 : [NET] : >>>> 'SL:17,01,04,04\r' 14:49:58,878 : [NET] : <<<< 'SL:P\r' 14:49:58,879 : [NET] : >>>> 'SL:18,01,04,04\r' 14:49:58,894 : [NET] : <<<< 'SL:P\r' 14:49:58,895 : [NET] : >>>> 'SL:19,01,04,04\r' 14:49:58,910 : [NET] : <<<< 'SL:P\r' 14:49:58,911 : [NET] : >>>> 'SL:1A,01,04,04\r' 14:49:58,926 : [NET] : <<<< 'SL:P\r' 14:49:58,927 : [NET] : >>>> 'SL:1B,01,04,04\r' 14:49:58,942 : [NET] : <<<< 'SL:P\r' 14:49:58,942 : [NET] : >>>> 'SL:1C,01,04,04\r' 14:49:58,958 : [NET] : <<<< 'SL:P\r' 14:49:58,958 : [NET] : >>>> 'SL:1D,01,04,04\r' 14:49:58,974 : [NET] : <<<< 'SL:P\r' 14:49:58,974 : [NET] : >>>> 'SL:1E,01,04,04\r' 14:49:58,990 : [NET] : <<<< 'SL:P\r' 14:49:58,990 : [NET] : >>>> 'SL:1F,01,04,04\r' 14:49:59,006 : [NET] : <<<< 'SL:P\r' 14:49:59,006 : [NET] : >>>> 'SL:20,01,04,04\r' 14:49:59,022 : [NET] : <<<< 'SL:P\r' 14:49:59,022 : [NET] : >>>> 'SL:21,01,04,04\r' 14:49:59,038 : [NET] : <<<< 'SL:P\r' 14:49:59,038 : [NET] : >>>> 'SL:22,01,04,04\r' 14:49:59,054 : [NET] : <<<< 'SL:P\r' 14:49:59,054 : [NET] : >>>> 'SL:27,01,04,04\r' 14:49:59,071 : [NET] : <<<< 'SL:P\r' 14:49:59,072 : [NET] : >>>> 'SL:24,01,04,04\r' 14:49:59,086 : [NET] : <<<< 'SL:P\r' 14:49:59,087 : [NET] : >>>> 'SL:25,01,04,04\r' 14:49:59,102 : [NET] : <<<< 'SL:P\r' 14:49:59,103 : [NET] : >>>> 'SL:26,01,04,04\r' 14:49:59,117 : [NET] : <<<< 'SL:P\r' 14:49:59,118 : [NET] : >>>> 'SL:23,01,04,04\r' 14:49:59,134 : [NET] : <<<< 'SL:P\r' 14:49:59,134 : [NET] : >>>> 'SL:28,01,04,04\r' 14:49:59,150 : [NET] : <<<< 'SL:P\r' 14:49:59,150 : [NET] : >>>> 'SL:29,01,04,04\r' 14:49:59,166 : [NET] : <<<< 'SL:P\r' 14:49:59,166 : [NET] : >>>> 'SL:2A,01,04,04\r' 14:49:59,182 : [NET] : <<<< 'SL:P\r' 14:49:59,182 : [NET] : >>>> 'SL:2C,01,04,04\r' 14:49:59,198 : [NET] : <<<< 'SL:P\r' 14:49:59,198 : [NET] : >>>> 'SL:2E,01,04,04\r' 14:49:59,214 : [NET] : <<<< 'SL:P\r' 14:49:59,214 : [NET] : >>>> 'SL:2F,01,04,04\r' 14:49:59,230 : [NET] : <<<< 'SL:P\r' 14:49:59,230 : [NET] : >>>> 'SL:38,01,04,04\r' 14:49:59,249 : [NET] : <<<< 'SL:P\r' 14:49:59,249 : [NET] : >>>> 'SL:39,01,04,04\r' 14:49:59,262 : [NET] : <<<< 'SL:P\r' 14:49:59,262 : [NET] : >>>> 'SL:3A,01,04,04\r' 14:49:59,278 : [NET] : <<<< 'SL:P\r' 14:49:59,278 : [NET] : >>>> 'SL:3B,01,04,04\r' 14:49:59,293 : [NET] : <<<< 'SL:P\r' 14:49:59,294 : [NET] : >>>> 'SL:3C,01,04,04\r' 14:49:59,310 : [NET] : <<<< 'SL:P\r' 14:49:59,310 : [NET] : >>>> 'SL:2B,01,04,04\r' 14:49:59,326 : [NET] : <<<< 'SL:P\r' 14:49:59,326 : [NET] : >>>> 'SL:2D,01,04,04\r' 14:49:59,342 : [NET] : <<<< 'SL:P\r' 14:49:59,342 : [NET] : >>>> 'SL:40,01,04,04\r' 14:49:59,358 : [NET] : <<<< 'SL:P\r' 14:49:59,358 : [NET] : >>>> 'SL:41,01,04,04\r' 14:49:59,374 : [NET] : <<<< 'SL:P\r' 14:49:59,374 : [NET] : >>>> 'SL:42,01,04,04\r' 14:49:59,390 : [NET] : <<<< 'SL:P\r' 14:49:59,390 : [NET] : >>>> 'SL:43,01,04,04\r' 14:49:59,406 : [NET] : <<<< 'SL:P\r' 14:49:59,406 : [NET] : >>>> 'SL:44,01,04,04\r' 14:49:59,422 : [NET] : <<<< 'SL:P\r' 14:49:59,422 : [NET] : >>>> 'SL:45,01,04,04\r' 14:49:59,438 : [NET] : <<<< 'SL:P\r' 14:49:59,438 : [NET] : >>>> 'SL:46,01,04,04\r' 14:49:59,454 : [NET] : <<<< 'SL:P\r' 14:49:59,455 : [NET] : >>>> 'SA:\r' 14:49:59,471 : [NET] : <<<< 'SA:0E,00107C00773F0001000000000000\r' 14:49:59,472 : [NET] : >>>> 'WD:7D0\r'
- The line above and this CR are the 1024 null characters which are sent to clear out any buffers. Below we get the expected
XX:Fresponse since this is not technically a valid command.
Documentation Feedback? Requests? Confused?
Hi! I'm Brian, and I'm responsible for the documentation at FAST Pinball. If you have any feedback, requests, corrections, ideas, or any other thoughts about the docs, please let me know!
You can email me at email@example.com. I maintain this site in my spare time, so there might be a week or so delay if you email me.
If you have a more pressing need, reach out to us via Slack, or email Aaron Davis.
N or > jump the next page, P or < for previous, search with S or ?