A quick look at the Firmware

The guide I wrote about building a F/A-18 UFC-like control box based on Arduino uses doens’t need any modification to the firmware hence no coding whatsoever: just get the firmware, load up the libraries and write it. I wrote about the steps required to set up Arduino here.

But what if you want to divert from the guide, maybe adding an encoder or two? Adjusting the wiring diagram is easy: starting from the now well-known diagram, you just need to resize the button matrix. Once the diagram has been adjusted, the soldering and testing is done, it’s time to code.

NOTE: if you are in a hurry or know what you are doing already, you can grab the firmwares from the Download page.

Coding is easy!

Especially when you don’t have to code at all! In fact, as long as only variables such as the pins involved and the size of button matrix and the encoders are changed, there’s really not much to do.
Here are the parts of code you need to update to match your wiring diagram.


#define defines (no s**t Sherlock!) a constant value. The names are quite self-explanatory. NUMROTARIES and NUMBUTTONS define how many buttons and rotary encoders are present in your control box. The size of the matrix is defined by NUMROWS and NUMCOLS. The original author has decided to use only 24 buttons though, hence why NUMBUTTONS!=NUMROWS*NUMCOLS.
So, e.g. let’s change the code in order to make it work for my Radio Box (6x encoders, 3×3 button matrix):
#define NUMBUTTONS 9
#define NUMROWS 3
#define NUMCOLS 3

Quite simple, isn’t it?

Matrix Buttons

This bi-dimensional array may look complicated but it’s actually very simple: this is where each physical button is associated to the joystick output. If you don’t care about having buttons in a particular order (I do not. At all.) you can assign buttons in any order you want.
Following the previous example, a 3×3 matrix will look like:
byte buttons[NUMROWS][NUMCOLS] = {

As I said, please note that you can put virtually any value there.

Rotary Encoders

The definition of the rotary encoders a slighly more complicated. In order to understand how they work we must first take a look at the struct that defines this bi-dimensional array:
struct rotariesdef {
byte pin1;
byte pin2;
int ccwchar;
int cwchar;
volatile unsigned char state;

The struct tells us that the values of the array mean:
pin1 and pin2 are self-explanatory: they are the pins where the encoders are physically attached (→soldered).
cwchar and ccwchar are the joystick values sent to the PC when the encoder is rotated clock-wise or counter clock-wise. For instance, if cwchar = 12, when you rotate the encoder CW, your computer will show that the button number 12 has been pressed.
state is a variable that doesn’t concern us. Live it be!

Our example (the Radio Box) uses 6 encoders, therefore the new array will look like this:

rotariesdef rotaries[NUMROTARIES] {

The Matrix

Easy stuff here, just tell Arduino which pins are part of the matrix.
The Radio Box uses a 3×3 matrix, therefore:
byte rowPins[NUMROWS] = {21,20,19};
byte colPins[NUMCOLS] = {18,15,14};

A last detail

This is the initialization of the Joystick. See that 32? That’s the total amount of buttons included in your control box. I know what you are thinking: the aren’t 32 buttons here! And you are indeed correct: in fact you can change to value to match the number of buttons in your Control box. As long as that number is bigger than your buttons it’s not a problem. Windows USB Game Controllers test will show 32 buttons when you plug-in your box but you will be able to use just a part of those. Different story if your box has more buttons than 32 (my aux box has 70 buttons, my UFC has 80). In this case you have to adjust the value to match (or being highter than) the number of buttons of your box or you won’t be able to use most of them.


February ’19 – MFDs everywhere!

Quick update about my setup. Although I don’t fly the F/A-18 I decided to get a used set of TM MFD and split it with a friend, and set it up in the only position it doens’t impede my movements: the Virpil Throttle Desk Mount. I always wanted to put something there and the third MFD is probably the best option, since I can’t put it anywhere else.

This is the result, configured for the F/A-18.

My setup – February 2019

I am waiting for the F-14, probably the only FW module I will fly regualarly, to find out if I need ad hoc box for it. In that case, I will replace the Left MFD with a new Control Box (it takes a couple minutes to swap between control boxes anyway).

Arduino control box: The Radio Box

This is the second control box I built almost one year ago and it’s still the box I use the most. Its job is to make pushing between frequencies a much easier task: the Ka-50 has two radio, the R-800L1 and the R-828; the former is tuned by operating four knobs, the latter requires one. Each knob can be rotated CW and CCW for a total of 10 functions, plus the “tune” button required on the R828. It’s quite a number of buttons and during a mission, when maintaining close formation, scanning for targets or avoiding obstacles going head-down on the radio panel to tune the correct frequency is definitely not something you want to do!

But why are radios so important? SP pilots probably rarely use their radio but in MP is different, especially when flying in a group that uses SRS or UR. Any training session or mission in the 132nd Virtual Wing has one or more human controllers. The R-828 is used for intra-flight comms, therefore is usually just once wheres the R-800L1 instead is tuned to:

  1. ATIS, for the latest information about weather and QNH;
  2. Ground, to check-in and requesting taxi to runway;
  3. Tower, for departure;
  4. Control, after departure, en-route towards the AO;
  5. Additional controllers, such as JTAC or AWACS.

As you can see, a dedicated control box starts making sense 🙂

Radio Box V1: Buttons matrix + encoders

The first version of the control box was very simple: the 6 encoders use a total of 12 pins. The remaining formed a 3×3 button matrix.
The second row of encoders sported the pushbutton function; top-left there were 2x 3-way momentary switches.
Radio Box - Version 1Radio Box - Version 1
The use was simple: top row of encoders for the R-800L1, bottom-right encoder for the R828 (push for tuning); bottom-left encoder for the Kneeboard (push for toggling visibility). The big round button centers the Track IR by sending a keyboard command and the others were used for controlling lights.

Radio Box V2: Latched 3-way switches

While I was planning my next control box I got stuck into the problem of latched 3-way switches. There are a number of ways to deal with the issue and I decided to use voltage dividers. Voltage diverders are a very easy solution with a number of applications; in our case they will allow our Arduino Board to understand the position of the 3-way switch by effecting the reading of the analog pins.
The concept is simple (I will write a dedicate Arduino Pill about it at some point): each end of the switch is connected to either GND or Vcc each through a resistor therefore the position of the lever changes the value read on the analog pin in an unique way (alright, let’s pretend noise doens’t exist for a moment). Code-wise, a simple series of cascading IFs will associate the value to the correct button and fire the appropriate Joystick.setButton() event.
As you can see, this approach is very simple and straight-forward but has a major flaw: the number of analog pins on a board is limited therefore if more than four 3-way latched switches are required, different solutions must be used.
Radio Box - Version 2
In this image you can see the small board hosting the four resistor required to control the 2x 3-way latched switches. I have also added 2-way latched switch and left the three remaining pins for the encoders’ pushbutton function and the Track IR. The final result can be seen in any picture of my updated setup.

Exporting MPCD and avionics to a secondary monitor

Howdy! I have bought a small 7″ LCD, resolution 800×600 for my setup. Here’s a quick guide about how to export avionics to an external / secondary LCD or monitor.

My main monitor is a 1920×1080 23″ or something. It’s fairly small, due to the lack of space on my desk. I have configured the additional 7″ monitor as the primary then I created an ad hoc configuration for it. The simplest way to do this is by copying and existing similar config and edit it.
Monitor cfg files can be found in \Config\MonitorSetup.

I created a few different config files but most of them are similar so I’m going into the details of just three of them:

  • RW: a single file to display the ABRIS (Ka-50), the TV screen and the RWR of the SA342;
  • F/A-18: the AMPCD is not in a really comfortable position hence I decided to export it;
  • AV8B NA: just for the sake of experimenting, I have exported the Right PCD.

Setting up the Views

This is the file for the RW. The first part of the file is similar for both configs.
_ = function(p) return p; end;
name = _('RotaryWing');
Description = 'RotaryWing: Ka-50; SA342 profile'
Viewports =
Center =
x = 0;
y = 0;
width = 1920;
height = 1080;
viewDx = 0;
viewDy = 0;
aspect = 1.777;

x = 1921;
y = 0;
width = 600;
height = 800;

SA342_TV =
x = 1953;
y = 0;
width = 570;
height = 490;

GazelleRWR =
x = 2071;
y = 495;
width = 300;
height = 300;

UIMainView = Viewports.Center

Viewports describes the main monitor, RIGHT_MFCD represents the ABRIS (default name) wherease the other two entry are included using a different tecnique I will cover later.

This is the cfg file for exporting the AMPCD:

_ = function(p) return p; end;
name = _('fa18');
Description = 'fa18'
Viewports =
Center =
x = 0;
y = 0;
width = 1920;
height = 1080;
viewDx = 0;
viewDy = 0;
aspect = 1.777;

x = 1921;
y = 0;
width = 600;
height = 600;

F18RWR =
x = 1921;
y = 650;
width = 150;
height = 150;

UIMainView = Viewports.Center

It includes the code to export to the RWR. I am not currently using it since the monitor is not big enough to host both views (I have also attached a Thrustmaster MFD on top of it. Velcro rules!). I haven’t tried exporting the Left or Right MPCD but I guess the standard nomenclature will do (RIGHT_MFCD and LEFT_MFCD).

Last example, the Harrier’s Right MPCD. The beginning of the file is the same as the F/A-18 (of course the name and description are different) so I paste just the interesting part:
x = 1921;
y = 0;
width = 600;
height = 600;

Please not that this will not export the MPCD unless you bind the reletive buttons from the Controls options and activate the export in-game. The easiest way to find these controls is to open use the Search function, type “export” and bind them.

Binding the MPCD Export controls for the Harrier.

More lua editing

Now that the Views are up and running we need to tell DCS what to export. In some cases there’s no need to do it because DCS deals with that on its own, for instance the ABRIS or the AMPCD. In other cases, we have to manually specify what to export and link them to the Views.
NOTE: these files might be overwritten in case of Repairs or Updates. You can either make a copy of the modified file and overwrite the new file every time or use OvGME or similar tools.

Exporting SA342 RWR and TV

The RWR file is located in \Mods\aircraft\SA342\Cockpit\RWR\indicator\init.lua. This is the code I have appended in order to export the RWR:

As you can see, it’s quite easy. The same principle applies to the TV; its file is located in \Mods\aircraft\SA342\Cockpit\TV\Indicator\init.lua.


I have found these info on ED’s forum, credits to them.

Pictures time!

Some pics of the setup and the 7″ LCD. Note that the MPCD is not centered relatively to the TM MFD simply because of the position where I took the picture.

As usual, feel free to comment and ask if you need any help 🙂

132nd VW Training Mission: Op Snapshot

Training mission run last Sunday, it has been my first taste of multi-asset combined operation.. Juicy taste but also a very hard bite.

This slideshow requires JavaScript.

Asset that partecipated:
3x Ka-50
1x Mi-8
6x A-10C
6x F/A-18C
2x Controllers (ATC/AWACS)

Kudos to everyone involved in the planning; in particular AssafB, great mission maker, Junior that has prepared the RW package briefing and led it and the controllers. Coordinating so many assets plus having to deal with a good number of green pilots must have been tough!

This is an extract from my stream with complete Briefing and Debriefing. The full stream was 3h59’10”.

Arduino Control Box: a Step by Step Guide – Part 7 – Closing the cirle

At this point, the Control Box should be finished, the last step is downloading the firmware and upload it to the board. I have covered the whole process in this post.

Now it’s testing time!
In order to test buttons and encoders, you can use the Windows Game Controllers (Start→”Set Up USB controllers”). It can check the status of up to 32 buttons, so it’s very, very limited.

A great alternative is Pointy’s Joystick Test. This simple yet very useful program allows you to test way more buttons. I have used it to test both my Auxiliary Panel and the Virpil MongoosT-50 Throttle.

Throubleshooting this Control Box is quite straightforward: software-wise there’s little to nothing to do; the harware continuity test should have been performed and passed already.

Now open DCS and start assigning you buttons. The Control Box will be seen by DCS as any other controller such as joysticks or pedals and identified by the name you have defined when you have changed the VID and PID.

Assigning functions to the Control Boxes in DCS

Reviewing DCS-BIOS & TFT

Due to the changes to my setup, I had to rotate the TFT. I originally planned to rewrite the code from scratch since in the first implementation I have used different techniques but, at the end of the day, I decided to keep most of the code.

This is the original TFT for the Ka-50, based on DCS-BIOS:

..aaand *drum rolls* this is the new one!

The new implementation of the TFT

I haven’t recorded a video yet, I will do it sooner or later.
I have added a few useful information that normally are not easy to read, such as the RPM limits for the left and right engine (impossible to read if head-down or zoomed in), the UGM8 selector (НР/АКС in Russian) to check the ballistic settings before firing a rocket / gunpod and a reminder of the Auto/Manual authority over the weapons.
A message will also remind me when it’s time to turn on the fuel tanks Cross Feed, plus a status light will confirm the switch position. The four circles represents the external pumps: when they turn off, the external tank is empty.
Finally, the VVI is now digital, with a big symbol indicating the current status: ↑, ↓, =.