Skip to content

Commit

Permalink
AH-64D: Add Power Lever controls for Idle/Off and Finger Lifts
Browse files Browse the repository at this point in the history
Fixes #999

Also moves engine power lever to Left Console category. Finger lift and Idle/Off controls do not work for CP/G, which seems to be a module limitation.
  • Loading branch information
charliefoxtwo committed Aug 25, 2024
1 parent 69b5647 commit 16ec5e1
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 8 deletions.
11 changes: 11 additions & 0 deletions Scripts/DCS-BIOS/lib/modules/ICommand.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module("ICommand", package.seeall)

--- @enum ICommand
local ICommand = {
left_engine_start = 311,
right_engine_start = 312,
left_engine_stop = 313,
right_engine_stop = 314,
}

return ICommand
47 changes: 47 additions & 0 deletions Scripts/DCS-BIOS/lib/modules/Module.lua
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,53 @@ function Module:defineInputOnlyPushButton(identifier, device_id, command, catego
return control
end

--- Adds a push button with no outputs and which sends only a single specified input on press. This is useful when no draw arg is present to evaluate the state of a control.
--- @param identifier string the unique identifier for the control
--- @param device_id integer the dcs device id
--- @param command integer the dcs command to move the switch up or down
--- @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:defineInputOnlySetStatePushButton(identifier, device_id, command, category, description)
local control = Control:new(category, ControlType.action, identifier, description, {
SetStateInput:new(1, "Sends the command"),
}, {})

self:addControl(control)

self:addInputProcessor(identifier, function(value)
local dev = GetDevice(device_id)
local val = tonumber(value)
if dev and val then
dev:performClickableAction(command, val)
end
end)

return control
end

--- Adds an input-only control which performs a specific LoSetCommand with no arguments
--- @param identifier string the unique identifier for the control
--- @param iCommand ICommand the dcs icommand to move the switch up or down
--- @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:defineLoSetCommand(identifier, iCommand, category, description)
local control = Control:new(category, ControlType.action, identifier, description, {
ActionInput:new(ActionArgument.toggle, "Triggers the action"),
}, {})

self:addControl(control)

self:addInputProcessor(identifier, function(action)
if action == ActionArgument.toggle then
LoSetCommand(iCommand)
end
end)

return control
end

--- Adds a new rotary potentiometer with values between 0 and 65535
--- @param identifier string the unique identifier for the control
--- @param device_id integer the dcs device id
Expand Down
20 changes: 15 additions & 5 deletions Scripts/DCS-BIOS/lib/modules/aircraft_modules/AH-64D.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module("AH-64D", package.seeall)

local AH_64D_EUFD = require("Scripts.DCS-BIOS.lib.modules.displays.AH_64D_EUFD")
local Functions = require("Scripts.DCS-BIOS.lib.common.Functions")
local ICommand = require("Scripts.DCS-BIOS.lib.modules.ICommand")
local TextDisplay = require("Scripts.DCS-BIOS.lib.modules.TextDisplay")

local Module = require("Scripts.DCS-BIOS.lib.modules.Module")
Expand All @@ -14,6 +15,7 @@ local AH_64D = Module:new("AH-64D", 0x8000, { "AH-64D_BLK_II" })
-- remove Arg# PLT 956; CPG 957

local devices = {
CONTROL_INTERFACE = 2,
HOTAS_INPUT = 25,
}

Expand Down Expand Up @@ -606,7 +608,7 @@ AH_64D:definePushButton("PLT_T_WHEEL_UNLOCK_BTN", 5, 3003, 308, "PLT Left Consol
AH_64D:define3PosTumb("PLT_ROTOR_BRK", 5, 3001, 314, "PLT Left Console", "Pilot Rotor Brake Switch, OFF/BRK/LOCK")
AH_64D:definePushButton("PLT_APU_BTN", 6, 3001, 400, "PLT Left Console", "Pilot APU Pushbutton")
AH_64D:defineToggleSwitch("PLT_APU_BTN_CVR", 6, 3002, 401, "PLT Left Console", "Pilot APU Pushbutton Cover, OPEN/CLOSE")
AH_64D:definePotentiometer("PLT_PW_LVR_FRIC", 2, 3001, 633, { 0, 1 }, "PLT Left Console", "Pilot Power Lever Friction Adjustment Lever")
AH_64D:definePotentiometer("PLT_PW_LVR_FRIC", devices.CONTROL_INTERFACE, 3001, 633, { 0, 1 }, "PLT Left Console", "Pilot Power Lever Friction Adjustment Lever")
AH_64D:defineSpringloaded_3PosTumb("PLT_ENG1_START", 6, 3004, 3003, 317, "PLT Left Console", "Pilot No.1 Engine Start Switch, IGN ORIDE/START")
AH_64D:defineSpringloaded_3PosTumb("PLT_ENG2_START", 6, 3006, 3005, 318, "PLT Left Console", "Pilot No.2 Engine Start Switch, IGN ORIDE/START")

Expand Down Expand Up @@ -648,17 +650,17 @@ AH_64D:definePushButton("PLT_M4_TRIGGER", 9, 3009, 827, "PLT Cockpit", "Pilot M4
AH_64D:define3PosTumb("PLT_M4_SAVE", 9, 3007, 828, "PLT Cockpit", "Pilot M4 Safety")
AH_64D:definePushButton("PLT_DEFOG_BTN", 9, 3001, 356, "PLT Cockpit", "Pilot Defog Button")
AH_64D:defineTumb("PLT_WIPER_SW", 9, 3002, 357, 0.1, { -0.1, 0.2 }, nil, false, "PLT Cockpit", "Pilot Wiper Control Switch, PARK/OFF/LO/HI")
AH_64D:definePotentiometer("PLT_ENG_L_PW_LVR", 6, 3031, 398, { 0, 1 }, "PLT Cockpit", "Pilot Power Lever Smoothly (Left)")
AH_64D:definePotentiometer("PLT_ENG_R_PW_LVR", 6, 3032, 399, { 0, 1 }, "PLT Cockpit", "Pilot Power Lever Smoothly (Right)")
AH_64D:definePotentiometer("PLT_ENG_L_PW_LVR", 6, 3031, 398, { 0, 1 }, "PLT Left Console", "Pilot Power Lever Smoothly (Left)")
AH_64D:definePotentiometer("PLT_ENG_R_PW_LVR", 6, 3032, 399, { 0, 1 }, "PLT Left Console", "Pilot Power Lever Smoothly (Right)")
AH_64D:defineTumb("PLT_MASTER_IGN_SW", 3, 3003, 315, 0.5, { 0, 1 }, nil, false, "PLT Cockpit", "Pilot Master Ignition Switch, OFF/BATT/EXT PWR")

AH_64D:defineToggleSwitch("CPG_CANOPY", 9, 3006, 799, "CPG Cockpit", "Gunner Canopy, OPEN/CLOSE")
AH_64D:definePushButton("CPG_M4_TRIGGER", 9, 3010, 825, "CPG Cockpit", "Gunner M4 Trigger")
AH_64D:define3PosTumb("CPG_M4_SAVE", 9, 3008, 826, "CPG Cockpit", "Gunner M4 Safety")
AH_64D:definePushButton("CPG_DEFOG_BTN", 9, 3003, 394, "CPG Cockpit", "Gunner Defog Button")
AH_64D:defineTumb("CPG_WIPER_SW", 9, 3004, 395, 0.1, { -0.1, 0.2 }, nil, false, "CPG Cockpit", "Gunner Wiper Control Switch, PARK/OFF/LO/HI")
AH_64D:definePotentiometer("CPG_ENG_L_PW_LVR", 6, 3031, 398, { 0, 1 }, "CPG Cockpit", "Gunner Power Lever Smoothly (Left)")
AH_64D:definePotentiometer("CPG_ENG_R_PW_LVR", 6, 3032, 399, { 0, 1 }, "CPG Cockpit", "Gunner Power Lever Smoothly (Right)")
AH_64D:definePotentiometer("CPG_ENG_L_PW_LVR", 6, 3031, 398, { 0, 1 }, "CPG Left Console", "Gunner Power Lever Smoothly (Left)")
AH_64D:definePotentiometer("CPG_ENG_R_PW_LVR", 6, 3032, 399, { 0, 1 }, "CPG Left Console", "Gunner Power Lever Smoothly (Right)")
AH_64D:defineToggleSwitch("CPG_STICK_FOLD", 87, 3007, 809, "CPG Cockpit", "Gunner Stick Folding, UP/DOWN")
AH_64D:define3PosTumb("CPG_PROC_SEL_SW", 3, 3004, 397, "CPG Cockpit", "Gunner Processor Select Switch, SP 1/AUTO/SP 2")

Expand Down Expand Up @@ -1036,4 +1038,12 @@ AH_64D:definePushButton("CPG_CYCLIC_CHAFF", devices.HOTAS_INPUT, 3021, 575, CYCL
AH_64D:definePushButton("CPG_CYCLIC_FLARE", devices.HOTAS_INPUT, 3022, 572, CYCLIC_CPG, "Flare Dispense")
AH_64D:definePushButton("CPG_CYCLIC_ATA_CAGE", devices.HOTAS_INPUT, 3023, 576, CYCLIC_CPG, "ATA Missile Cage/Uncage Button")

-- additional throttle lever controls (these don't seem to work for the CP/G)
AH_64D:defineInputOnlySetStatePushButton("PLT_ENG_L_PW_LVR_LIFT", devices.CONTROL_INTERFACE, 3011, "PLT Left Console", "Power Lever Finger Lift (Left)")
AH_64D:defineInputOnlySetStatePushButton("PLT_ENG_R_PW_LVR_LIFT", devices.CONTROL_INTERFACE, 3012, "PLT Left Console", "Power Lever Finger Lift (Right)")
AH_64D:defineLoSetCommand("PLT_ENG_L_PW_LVR_IDLE", ICommand.left_engine_start, "PLT Left Console", "Power Lever Idle (Left)")
AH_64D:defineLoSetCommand("PLT_ENG_R_PW_LVR_IDLE", ICommand.right_engine_start, "PLT Left Console", "Power Lever Idle (Right)")
AH_64D:defineLoSetCommand("PLT_ENG_L_PW_LVR_OFF", ICommand.left_engine_stop, "PLT Left Console", "Power Lever Off (Left)")
AH_64D:defineLoSetCommand("PLT_ENG_R_PW_LVR_OFF", ICommand.right_engine_stop, "PLT Left Console", "Power Lever Off (Right)")

return AH_64D
3 changes: 3 additions & 0 deletions Scripts/DCS-BIOS/test/ModuleTest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,6 @@ require("Scripts.DCS-BIOS.test.controls.EjectionHandleSwitchTest")
require("Scripts.DCS-BIOS.test.controls.SetCommandTumbTest")
require("Scripts.DCS-BIOS.test.controls.ReadOnlyRadioTest")
require("Scripts.DCS-BIOS.test.controls.ReadWriteRadioTest")
require("Scripts.DCS-BIOS.test.controls.InputOnlyPushButtonTest")
require("Scripts.DCS-BIOS.test.controls.InputOnlySetStatePushButtonTest")
require("Scripts.DCS-BIOS.test.controls.LoSetCommandTest")
5 changes: 2 additions & 3 deletions Scripts/DCS-BIOS/test/controls/InputOnlyPushButtonTest.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
local ActionArgument = require("Scripts.DCS-BIOS.lib.modules.documentation.ActionArgument")
local ApiVariant = require("Scripts.DCS-BIOS.lib.modules.documentation.ApiVariant")
local ControlType = require("Scripts.DCS-BIOS.lib.modules.documentation.ControlType")
local InputType = require("Scripts.DCS-BIOS.lib.modules.documentation.InputType")
local MockDevice = require("Scripts.DCS-BIOS.test.controls.MockDevice")
Expand Down Expand Up @@ -28,11 +27,11 @@ function TestInputOnlyPushButton:testAddPushButton()
local control = self.module:defineInputOnlyPushButton(id, device_id, command, category, description)

lu.assertEquals(control, self.module.documentation[category][id])
lu.assertEquals(control.control_type, ControlType.selector)
lu.assertEquals(control.control_type, ControlType.action)
lu.assertEquals(control.category, category)
lu.assertEquals(control.description, description)
lu.assertEquals(control.identifier, id)
lu.assertEquals(control.api_variant, ApiVariant.momentary_last_position)
lu.assertIsNil(control.api_variant)

lu.assertEquals(#control.inputs, 1)

Expand Down
64 changes: 64 additions & 0 deletions Scripts/DCS-BIOS/test/controls/InputOnlySetStatePushButtonTest.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
local ControlType = require("Scripts.DCS-BIOS.lib.modules.documentation.ControlType")
local InputType = require("Scripts.DCS-BIOS.lib.modules.documentation.InputType")
local MockDevice = require("Scripts.DCS-BIOS.test.controls.MockDevice")
local Module = require("Scripts.DCS-BIOS.lib.modules.Module")

local lu = require("Scripts.DCS-BIOS.test.ext.luaunit")

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

function TestInputOnlySetStatePushButton:setUp()
self.module = Module:new(moduleName, moduleAddress, {})
Input_Processor_Device = MockDevice:new(0)
end

local id = "MY_INPUT_ONLY_SET_STATE_PUSH_BUTTON"
local device_id = 1
local command = 2
local category = "Input-Only Set State Push Buttons"
local description = "This is an input-only set state push button"

function TestInputOnlySetStatePushButton:testAddPushButton()
local control = self.module:defineInputOnlySetStatePushButton(id, device_id, command, category, description)

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

lu.assertEquals(#control.inputs, 1)

local set_state_input = control.inputs[1] --[[@as SetStateInput]]
lu.assertEquals(set_state_input.interface, InputType.set_state)
lu.assertEquals(set_state_input.max_value, 1)

lu.assertEquals(#control.outputs, 0)
end

function TestInputOnlySetStatePushButton:testInput0()
self.module:defineInputOnlySetStatePushButton(id, device_id, command, category, description)
local input_processor = self.module.inputProcessors[id]

input_processor("0")

lu.assertEquals(#Input_Processor_Device.clickable_actions, 1)
local action_press = Input_Processor_Device.clickable_actions[1]
lu.assertAlmostEquals(action_press[command], 0)
end

function TestInputOnlySetStatePushButton:testInput1()
self.module:defineInputOnlySetStatePushButton(id, device_id, command, category, description)
local input_processor = self.module.inputProcessors[id]

input_processor("1")

lu.assertEquals(#Input_Processor_Device.clickable_actions, 1)
local action_press = Input_Processor_Device.clickable_actions[1]
lu.assertAlmostEquals(action_press[command], 1)
end
54 changes: 54 additions & 0 deletions Scripts/DCS-BIOS/test/controls/LoSetCommandTest.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
local ActionArgument = require("Scripts.DCS-BIOS.lib.modules.documentation.ActionArgument")
local ControlType = require("Scripts.DCS-BIOS.lib.modules.documentation.ControlType")
local ICommand = require("Scripts.DCS-BIOS.lib.modules.ICommand")
local InputType = require("Scripts.DCS-BIOS.lib.modules.documentation.InputType")
local MockDevice = require("Scripts.DCS-BIOS.test.controls.MockDevice")
local Module = require("Scripts.DCS-BIOS.lib.modules.Module")

local lu = require("Scripts.DCS-BIOS.test.ext.luaunit")

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

function TestLoSetCommand:setUp()
self.module = Module:new(moduleName, moduleAddress, {})
Input_Processor_Device = MockDevice:new(0)
end

local id = "MY_LO_SET_COMMAND"
local iCommand = ICommand.left_engine_start
local category = "LoSetCommands"
local description = "This is a LoSetCommand"

function TestLoSetCommand:testAddLoSetCommand()
local control = self.module:defineLoSetCommand(id, iCommand, category, description)

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

lu.assertEquals(#control.inputs, 1)

local action_input = control.inputs[1] --[[@as ActionInput]]
lu.assertEquals(action_input.interface, InputType.action)
lu.assertEquals(action_input.argument, ActionArgument.toggle)

lu.assertEquals(#control.outputs, 0)
end

function LoSetCommand(iCommand)
lu.assertEquals(ICommand.left_engine_start, iCommand)
end

function TestLoSetCommand:testLoSetCommand()
self.module:defineLoSetCommand(id, iCommand, category, description)
local input_processor = self.module.inputProcessors[id]

input_processor("TOGGLE")
end

0 comments on commit 16ec5e1

Please sign in to comment.