Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#248 Remove broken ACCELEROMETER_VALUE and add gauge value controls #261

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 23 additions & 41 deletions Scripts/DCS-BIOS/doc/json/P-51D.json

Large diffs are not rendered by default.

64 changes: 23 additions & 41 deletions Scripts/DCS-BIOS/doc/json/P-51D.jsonp

Large diffs are not rendered by default.

7 changes: 0 additions & 7 deletions Scripts/DCS-BIOS/lib/meta_files/DCS_API_defs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,6 @@ CockpitPage = ""
--- @return string[]
function list_cockpit_params() end

--- @func Maps value to from input_range to output_range
--- @param argument_value number
--- @param input_range table<number>
--- @param output_range table<number>
--- @return number
function ValueConvert(argument_value, input_range, output_range) end

--- @func Returns altitude above sea level
--- @return number
function LoGetAltitudeAboveSeaLevel() end
Expand Down
45 changes: 41 additions & 4 deletions Scripts/DCS-BIOS/lib/modules/Module.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,36 @@ function Module:new(name, baseAddress, acftList)
return o
end

--- Reserves space in the memory map for an integer with the specified max value
---@param max_value integer the max value of the integer to reserve space for
function Module:reserveIntValue(max_value)
self:allocateInt(max_value)
end

--- Defines a gauge from floating-point data with limits. This generally is not used in any new modules and is used in existing modules to provide the integer output of a gauge
--- @param identifier string the unique identifier for the control
--- @param arg_number integer the dcs argument number
--- @param output_range number[] a length-2 array with the lower and upper bounds of the output data - lower bound must be greater than or equal to zero
--- @param category string the category in which the control should appear
--- @param description string additional information about the control
--- @return Control control the control which was added to the module
function Module:defineGaugeValue(identifier, arg_number, output_range, category, description)
assert(output_range[1] >= 0)

local max_value = 65535
local alloc = self:allocateInt(max_value)
self:addExportHook(function(dev0)
alloc:setValue(Module.valueConvert(dev0:get_argument_value(arg_number), { 0, 1 }, output_range))
end)

local control = Control:new(category, ControlType.metadata, identifier, description, {}, {
IntegerOutput:new(alloc, Suffix.none, description),
})
self:addControl(control)

return control
end

--- Defines a gauge from floating-point data with limits
--- @param identifier string the unique identifier for the control
--- @param arg_number integer the dcs argument number
Expand All @@ -54,15 +84,12 @@ end
--- @param description string additional information about the control
--- @return Control control the control which was added to the module
function Module:defineFloat(identifier, arg_number, limits, category, description)
local intervalLength = limits[2] - limits[1]
local max_value = 65535
local alloc = self:allocateInt(max_value)

self:addExportHook(function(dev0)
alloc:setValue(((dev0:get_argument_value(arg_number) - limits[1]) / intervalLength) * max_value)
alloc:setValue(Module.valueConvert(dev0:get_argument_value(arg_number), limits, { 0, max_value }))
end)

-- todo: almost identical to below for allocating an int, just different descriptions?
local control = Control:new(category, ControlType.analog_gauge, identifier, description, {}, {
IntegerOutput:new(alloc, Suffix.none, "gauge position"),
})
Expand Down Expand Up @@ -745,4 +772,14 @@ function Module.round(num)
return num >= 0 and math.floor(num + 0.5) or math.ceil(num - 0.5)
end

--- @func Maps value to from input_range to output_range
--- @param argument_value number the number to map
--- @param input_range number[] a length-2 array of the range of the input value
--- @param output_range number[] a length-2 array of the range the value should be mapped to
--- @return number
function Module.valueConvert(argument_value, input_range, output_range)
local slope = 1.0 * (output_range[2] - output_range[1]) / (input_range[2] - input_range[1])
return output_range[1] + slope * (argument_value - input_range[1])
end

return Module
114 changes: 19 additions & 95 deletions Scripts/DCS-BIOS/lib/modules/aircraft_modules/P-51D.lua
Original file line number Diff line number Diff line change
Expand Up @@ -169,119 +169,43 @@ P_51D:defineBitFromDrawArgument("EXT_RECOC_LIGHT_YE", 202, "External Aircraft Mo

--[[--Gauge Values--]]
--
local function getAirspeed()
local returnValue = (GetDevice(0):get_argument_value(11)) * 1000
return returnValue
end
P_51D:defineIntegerFromGetter("AIRSPEED_MPH_VALUE", getAirspeed, 65000, "Gauge Values", "Airspeed MPH")
P_51D:defineGaugeValue("AIRSPEED_MPH_VALUE", 11, { 0, 1000 }, "Gauge Values", "Airspeed MPH")

local function getAltitude()
local returnValue = (GetDevice(0):get_argument_value(96)) * 100000
return returnValue
end
P_51D:defineIntegerFromGetter("ALTIMETER_VALUE", getAltitude, 65000, "Gauge Values", "Altimeter")
P_51D:defineGaugeValue("ALTIMETER_VALUE", 96, { 0, 100000 }, "Gauge Values", "Altimeter")

local function getEngineRPM()
local returnValue = (GetDevice(0):get_argument_value(23)) * 4500
return returnValue
end
P_51D:defineIntegerFromGetter("ENGINE_RPM_VALUE", getEngineRPM, 65000, "Gauge Values", "Engine RPM Value")
P_51D:defineGaugeValue("ENGINE_RPM_VALUE", 23, { 0, 4500 }, "Gauge Values", "Engine RPM Value")

local function getGyro()
local returnValue = (GetDevice(0):get_argument_value(12)) * 360
return returnValue
end
P_51D:defineIntegerFromGetter("DIRECTIONAL_GYRO_VALUE", getGyro, 65000, "Gauge Values", "Directional Gyro")
P_51D:defineGaugeValue("DIRECTIONAL_GYRO_VALUE", 12, { 0, 360 }, "Gauge Values", "Directional Gyro")

local function getHDG()
local returnValue = (GetDevice(0):get_argument_value(1)) * 360
return returnValue
end
P_51D:defineIntegerFromGetter("HEADING_VALUE", getHDG, 65000, "Gauge Values", "Remote Compass Heading")
P_51D:defineGaugeValue("HEADING_VALUE", 1, { 0, 360 }, "Gauge Values", "Remote Compass Heading")

local function getCRS()
local returnValue = (GetDevice(0):get_argument_value(2)) * 360
return returnValue
end
P_51D:defineIntegerFromGetter("COURSE_VALUE", getCRS, 65000, "Gauge Values", "Remote Compass Course")
P_51D:defineGaugeValue("COURSE_VALUE", 2, { 0, 360 }, "Gauge Values", "Remote Compass Course")

local function getFuelPres()
local returnValue = (GetDevice(0):get_argument_value(32)) * 25
return returnValue
end
P_51D:defineIntegerFromGetter("FUEL_PRESSURE_VALUE", getFuelPres, 65000, "Gauge Values", "Fuel Pressure")
P_51D:defineGaugeValue("FUEL_PRESSURE_VALUE", 32, { 0, 25 }, "Gauge Values", "Fuel Pressure")

local function getHydPres()
local returnValue = (GetDevice(0):get_argument_value(78)) * 2000
return returnValue
end
P_51D:defineIntegerFromGetter("HYDRAULIC_PRESSURE_VALUE", getHydPres, 65000, "Gauge Values", "Hydraulic Pressure")
P_51D:defineGaugeValue("HYDRAULIC_PRESSURE_VALUE", 78, { 0, 2000 }, "Gauge Values", "Hydraulic Pressure")

local function getManifoldPres()
local returnValue = (GetDevice(0):get_argument_value(10)) * 65 + 10
return returnValue
end
P_51D:defineIntegerFromGetter("MANIFOLD_PRESSURE_VALUE", getManifoldPres, 65000, "Gauge Values", "Manifold Pressure")
P_51D:defineGaugeValue("MANIFOLD_PRESSURE_VALUE", 10, { 10, 75 }, "Gauge Values", "Manifold Pressure")

local function getVacuum()
local returnValue = (GetDevice(0):get_argument_value(9)) * 100
return returnValue
end
P_51D:defineIntegerFromGetter("VACUUM_SUCTION_VALUE", getVacuum, 65000, "Gauge Values", "Vacuum Suction read as X.X or XX.X")
P_51D:defineGaugeValue("VACUUM_SUCTION_VALUE", 9, { 0, 100 }, "Gauge Values", "Vacuum Suction read as X.X or XX.X")

local function getOilTemp()
local returnValue = (GetDevice(0):get_argument_value(30)) * 100
return returnValue
end
P_51D:defineIntegerFromGetter("OIL_TEMPERATURE_VALUE", getOilTemp, 65000, "Gauge Values", "Oil Temperature")
P_51D:defineGaugeValue("OIL_TEMPERATURE_VALUE", 30, { 0, 100 }, "Gauge Values", "Oil Temperature")

local function getOilPres()
local returnValue = (GetDevice(0):get_argument_value(31)) * 200
return returnValue
end
P_51D:defineIntegerFromGetter("OIL_PRESSURE_VALUE", getOilPres, 65000, "Gauge Values", "Oil Pressure")
P_51D:defineGaugeValue("OIL_PRESSURE_VALUE", 31, { 0, 200 }, "Gauge Values", "Oil Pressure")

local function getAmps()
local returnValue = (GetDevice(0):get_argument_value(101)) * 150
return returnValue
end
P_51D:defineIntegerFromGetter("AMMETER_VALUE", getAmps, 65000, "Gauge Values", "Ammeter")
P_51D:defineGaugeValue("AMMETER_VALUE", 101, { 0, 150 }, "Gauge Values", "Ammeter")

local function getOxygen()
local returnValue = (GetDevice(0):get_argument_value(34)) * 500
return returnValue
end
P_51D:defineIntegerFromGetter("OXYGEN_PRESSURE_VALUE", getOxygen, 65000, "Gauge Values", "Oxygen Pressure")
P_51D:defineGaugeValue("OXYGEN_PRESSURE_VALUE", 34, { 0, 500 }, "Gauge Values", "Oxygen Pressure")

local function getLeftFuel()
local returnValue = (GetDevice(0):get_argument_value(155)) * 92
return returnValue
end
P_51D:defineIntegerFromGetter("LEFT_FUEL_TANK_VALUE", getLeftFuel, 65000, "Gauge Values", "Left Fuel Tank Gallons")
P_51D:defineGaugeValue("LEFT_FUEL_TANK_VALUE", 155, { 0, 92 }, "Gauge Values", "Left Fuel Tank Gallons")

local function getRightFuel()
local returnValue = (GetDevice(0):get_argument_value(156)) * 92
return returnValue
end
P_51D:defineIntegerFromGetter("RIGHT_FUEL_TANK_VALUE", getRightFuel, 65000, "Gauge Values", "Right Fuel Tank Gallons")
P_51D:defineGaugeValue("RIGHT_FUEL_TANK_VALUE", 156, { 0, 92 }, "Gauge Values", "Right Fuel Tank Gallons")

local function getFuseFuel()
local returnValue = (GetDevice(0):get_argument_value(160)) * 85
return returnValue
end
P_51D:defineIntegerFromGetter("FUSELAGE_FUEL_TANK_VALUE", getFuseFuel, 65000, "Gauge Values", "Fuselage Fuel Tank Gallons")
P_51D:defineGaugeValue("FUSELAGE_FUEL_TANK_VALUE", 160, { 0, 85 }, "Gauge Values", "Fuselage Fuel Tank Gallons")

local function getBaro()
local returnValue = (GetDevice(0):get_argument_value(97)) * 290 + 2810
return returnValue
end
P_51D:defineIntegerFromGetter("BAROMETRIC_PRESSURE_VALUE", getBaro, 65000, "Gauge Values", "Barometric Pressure")
P_51D:defineGaugeValue("BAROMETRIC_PRESSURE_VALUE", 97, { 2810, 3100 }, "Gauge Values", "Barometric Pressure")

local function getAccel()
local returnValue = (GetDevice(0):get_argument_value(175)) * 17 - 5
return returnValue
end
P_51D:defineIntegerFromGetter("ACCELEROMETER_VALUE", getAccel, 65000, "Gauge Values", "Accelerometer")
P_51D:reserveIntValue(65535) -- removed non-functional ACCELEROMETER_VALUE (#248)

P_51D:defineIndicatorLight("WINDSHIELD_OIL_L", 412, "Damage", "Windshield Oil Splashes (black)")
P_51D:defineFloat("WINDSHIELD_CRACKS", 413, { 0, 1 }, "Damage", "Windshield Crack Holes")
Expand Down
6 changes: 1 addition & 5 deletions Scripts/DCS-BIOS/test/ModuleTest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ TestModule = {}
local moduleName = "MyModule"
local moduleAddress = 0x4200

function ValueConvert(value, input_range, output_range)
local slope = 1.0 * (output_range[2] - output_range[1]) / (input_range[2] - input_range[1])
return output_range[1] + slope * (value - input_range[1])
end

function TestModule:setUp()
self.module = Module:new(moduleName, moduleAddress, {})
end
Expand All @@ -33,6 +28,7 @@ function LoGetAircraftDrawArgumentValue()
return GetDevice().value
end

require("GaugeValueTest")
require("FloatTest")
require("IndicatorLightTest")
require("GatedIndicatorLightTest")
Expand Down
84 changes: 84 additions & 0 deletions Scripts/DCS-BIOS/test/controls/GaugeValueTest.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
local ControlType = require("ControlType")
local MockDevice = require("MockDevice")
local Module = require("Module")
local OutputType = require("OutputType")
local Suffix = require("Suffix")

local lu = require("luaunit")

--- @class TestGaugeValue
--- @field module Module
TestGaugeValue = {}
local moduleName = "MyModule"
local moduleAddress = 0x4200

function TestGaugeValue:setUp()
self.module = Module:new(moduleName, moduleAddress, {})
end

local id = "MY_GAUGE_VALUE"
local arg_number = 1
local category = "Gauge Values"
local description = "This is a gauge value"

function TestGaugeValue:testAddGaugeValue()
local limits = { 0, 1 }

local control = self.module:defineGaugeValue(id, arg_number, limits, category, description)

lu.assertEquals(control, self.module.documentation[category][id])
lu.assertEquals(control.control_type, ControlType.metadata)
lu.assertEquals(control.category, category)
lu.assertEquals(control.description, description)
lu.assertEquals(control.identifier, id)
lu.assertIsNil(control.physical_variant)
lu.assertIsNil(control.api_variant)

lu.assertEquals(#control.inputs, 0)

lu.assertEquals(#control.outputs, 1)
local output = control.outputs[1] --[[@as IntegerOutput]]
lu.assertEquals(output.type, OutputType.integer)
lu.assertEquals(output.max_value, 65535)
lu.assertEquals(output.suffix, Suffix.none)
lu.assertEquals(output.description, description)
lu.assertEquals(output.address, moduleAddress) -- first control, should be plenty of room, no need to move the address
end

function TestGaugeValue:testGaugeValueZeroMinValue()
local limits = { 0, 500 }

self.module:defineGaugeValue(id, arg_number, limits, category, description)

local export_hook = self.module.exportHooks[1]

local alloc = self.module.memoryMap.entries[moduleAddress].allocations[1]

export_hook(MockDevice:new(0))
lu.assertEquals(alloc.value, 0)

export_hook(MockDevice:new(0.5))
lu.assertEquals(alloc.value, 250)

export_hook(MockDevice:new(1))
lu.assertEquals(alloc.value, 500)
end

function TestGaugeValue:testGaugeValuePositiveMinValue()
local limits = { 10, 75 }

self.module:defineGaugeValue(id, arg_number, limits, category, description)

local export_hook = self.module.exportHooks[1]

local alloc = self.module.memoryMap.entries[moduleAddress].allocations[1]

export_hook(MockDevice:new(0))
lu.assertEquals(alloc.value, 10)

export_hook(MockDevice:new(0.5))
lu.assertEquals(alloc.value, 42)

export_hook(MockDevice:new(1))
lu.assertEquals(alloc.value, 75)
end