Jump to content

DCS-BIOS arduino code for switching between modules


ctytler

Recommended Posts

I was searching the forums and couldn't find any discussion on how to set up an Arduino board to enable/disable functionality based on Module. So I came up with a method to do so for LEDs and thought I'd share if it's useful to anyone else.

 

Here is an example sketch to set up a Master Caution indicator light for multiple modules for a single LED. It's done with a wrapper around the DcsBios::LED class that can set it active or deactive.

 

Note the code copy/pasted from the Control Reference is modified to be a ModuleLED instead of DcsBios::LED and includes the aircraft module name as the first argument -- this name must match the names used for the modules by the game. You'll also see that "A-10C" and "A-10C_2" are considered different modules so each are there with the same values.

 

#define DCSBIOS_DEFAULT_SERIAL
#include <DcsBios.h>

constexpr int kPinMasterCautionLed = 15; /// Pin number LED is connected to.

// ModuleLED: This is a wrapper around the standard DcsBios::LED that allows
// the functionality to only be enabled when the specified module is in use.
class ModuleLED : public DcsBios::LED
{
private:
    char *moduleName;
    bool is_active = false;
    unsigned char pin;

public:
    ModuleLED(char *moduleName, unsigned int address, unsigned int mask, char pin)
        : moduleName(moduleName), pin(pin), DcsBios::LED(address, mask, pin) {}
    virtual void loop()
    {
        if (is_active)
        {
            DcsBios::LED::loop();
        }
    }
    void set_active_according_to_module(char *newValue)
    {
        digitalWrite(pin, LOW); // Turn off by default until turned on again by module.
        is_active = !strcmp(moduleName, newValue);
    }
};

// Define all LEDs in an array to easily loop through them later.
ModuleLED leds[] = {
    ModuleLED("A-10C", 0x1012, 0x0800, kPinMasterCautionLed),
    ModuleLED("A-10C_2", 0x1012, 0x0800, kPinMasterCautionLed),
    ModuleLED("AV8BNA", 0x7860, 0x1000, kPinMasterCautionLed),
    ModuleLED("FA-18C_hornet", 0x7408, 0x0200, kPinMasterCautionLed),
    ModuleLED("F-16C_50", 0x4472, 0x0800, kPinMasterCautionLed),
    ModuleLED("UH-1H", 0x1416, 0x0100, kPinMasterCautionLed),
};

// This callback function is called every aircraft change with the module name as newValue.
void onAcftNameChange(char *newValue)
{
    const size_t number_of_leds = sizeof(leds) / sizeof((leds)[0]);
    for (size_t i = 0; i < number_of_leds; i++)
    {
        leds[i].set_active_according_to_module(newValue);
    }
}
DcsBios::StringBuffer<24> AcftNameBuffer(0x0000, onAcftNameChange);

// For reference, these are the copy/paste code snippets as found in
// the DCS-BIOS Control Reference that were modified.
//   DcsBios::LED masterCaution(0x1012, 0x0800, PIN);      // From A-10C
//   DcsBios::LED mcLight(0x7860, 0x1000, PIN);            // From AV8BNA
//   DcsBios::LED masterCautionLt(0x7408, 0x0200, PIN);    // From FA-18C
//   DcsBios::LED lightMasterCaution(0x4472, 0x0800, PIN); // From F-16C
//   DcsBios::LED masterCautionInd(0x1416, 0x0100, PIN);   // From UH-1H

void setup() {
    DcsBios::setup();
}

void loop() {
    DcsBios::loop();
}

 


Edited by ctytler
Removed unnecessary line from code
Link to comment
Share on other sites

  • 4 months later...

Why do you have to know which module is running?
Why not just call the same light-handling function with the "onChange" function for the modules?
e.g.
 

#define DCSBIOS_IRQ_SERIAL
#include "DcsBios.h"

#define mcLEDpin 13

// Common light function
void onMasterCautionChange(unsigned int newValue) {
  if (newValue > 0) {
    digitalWrite (mcLEDpin, HIGH); // Turn on LED
    }
  else {
    digitalWrite (mcLEDpin, LOW);  // Turn off LED
    }
}

// A-10 call
DcsBios::IntegerBuffer masterCautionBuffer(0x1012, 0x0800, 11, onMasterCautionChange);

// F-16 call

DcsBios::IntegerBuffer lightMasterCautionBuffer(0x4476, 0x0080, 7, onMasterCautionChange);

// P-51 landing gear red light
DcsBios::IntegerBuffer landingGearRedBuffer(0x500e, 0x4000, 14, onMasterCautionChange);

void setup() {
  DcsBios::setup();
}

void loop() {
  DcsBios::loop();
}


I just tested that code in a Nano.
On the P-51, pressing the Unsafe Landing Gear Light Test turned on the LED.
In the same DCS session, with no reset of the arduino, the LED responded to the A-10 Master Caution light.
I don't have the F-16, so can't test that, but having the code in there didn't affect anything.

You'd obviously need to check for address conflicts, and I may be missing some other issues, but for LEDs at least, it seems to be far less complicated than you make it appear.

  • Thanks 2
Link to comment
Share on other sites

Having thought a bit more, I wondered if it works for input too.
And it DOES!

Added this in:
 

#define mcSWpin 2  // Added at top of code

DcsBios::Switch2Pos ufcMasterCaution("UFC_MASTER_CAUTION", mcSWpin); // A-10 Master Caution Switch
DcsBios::Switch2Pos unsafeLndGearLtTest("UNSAFE_LND_GEAR_LT_TEST", mcSWpin); // P-51 landing gear red light test switch

And now, a single switch on the Nano either activates the P-51 unsafe gear light test or the A-10 Master Caution reset depending on which aircraft you're using.

Again, same caveats that there's no conflicts in these functions, but there might be in others.


Edited by No1sonuk
  • Thanks 1
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...