Found an API reference.
This should be close to the final deal.
---------------------------------------------------------------
-- Added by DG May 30 2021 to enable the control panel
-- Monitor the switches on the control panel.
-- We break the three different mechanical switches into three separate function calls, since each function has a separate job.
-- We don't need to assign the MPG wheel since Mach handles that for us.
---------------------------------------------------------------
SigLib = {
-------------
-- Axis Select Switch
-- Must always be X or Y
    [mc.ISIG_INPUT0] = function (state)   -- X Axis Select TODO set correct signal number
        PendantAxisChange()                     
    end,
    [mc.ISIG_INPUT1] = function (state)   -- Y Axis Select TODO set correct signal number
        PendantAxisChange()                     
    end,
-------------
-- Jog Enable / Speed
-- 4-position rotary switch
-- No active signals mean JOG OFF
    [mc.ISIG_INPUT6] = function (state)       -- Enable Jog Speed 0.1 TODO set correct signal number
        PendantSpeedChange()                 
    end,
    [mc.ISIG_INPUT7] = function (state)       -- Enable Jog Speed 0.01 TODO set correct signal number
        PendantSpeedChange()                 
    end,
    [mc.ISIG_INPUT8] = function (state)       -- Enable Jog Speed 0.001 TODO set correct signal number
        PendantSpeedChange()                     
    end,
-------------
-- Cycle Start Panel Button
    [mc.ISIG_INPUT10] = function (state)      -- TODO set correct signal number      
         InputCycleStart()
    end,
--------------
-- Feed Hold Panel Button
    [mc.ISIG_INPUT11] = function (state)      -- TODO set correct signal number      
        InputFeedHold()
    end,
---------------
-- Manual Spindle ON/OFF Panel Button
    [mc.ISIG_INPUT12] = function (state)      -- Starts the spindle manually TODO set correct signal number
        InputManualSpindle()
    end
}
---------------------------------------------------------------
-- Control Panel Cycle Start
---------------------------------------------------------------
function InputCycleStart()
        -- Momentary pushbutton, so we get TWO signals with each button press:
        -- an "ON" and an "OFF"
        -- So check state and ignore the "OFF"
        local hStartButton
	local StartButtonState
	hStartButton, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT8)      -- TODO set correct signal
        StartButtonState, rc = mc.mcSignalGetState(hStartButton)
        mc.mcCntlSetLastError(inst, "Control Panel Cycle Start PRESS")
        if (StartButtonState == 1) then 
   	    local hRunLight
   	    hRunLight, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1) --TODO set correct signal number
   	    local hHoldLight
   	    hHoldLight, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1) --TODO set correct signal number
   	    mc.mcSignalSetState(hHoldLight, 0)       -- Make sure the HOLD light is off
   	    mc.mcSignalSetState(hRunLight, 1)        -- Turn the RUN light on
   	    CycleStart()
   	    mc.mcCntlSetLastError(inst, "Control Panel CYCLE START")
        else
            mc.mcCntlSetLastError(inst, "Control Panel Cycle Start RELEASE")
	end
end
---------------------------------------------------------------
-- Control Panel Feed Hold
-- One push for Feed Hold, two pushes for Cycle Stop
---------------------------------------------------------------
function InputFeedHold()
	-- Momentary pushbutton, so we get TWO signals with each button press:
        -- an "ON" and an "OFF"
        -- So check state and ignore the "OFF"
        local hHoldButton
	local HoldButtonState
	hHoldButton, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT8)      -- TODO set correct signal
        HoldButtonState, rc = mc.mcSignalGetState(hHoldButton)
        if (HoldButtonState == 1) then
   	    local hRunLight
   	    hRunLight, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1)  -- TODO set correct signal number
   	    local hHoldLight
   	    hHoldLight, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1) -- TODO set correct signal number
            mc.mcCntlSetLastError(inst, "Control Panel Feed Hold PRESS")
            -- If we are running a program, pause
            -- If we are already paused, stop
            local Running
            local Paused
            Running, rc = mc.mcCntlIsInCycle(inst)
            Paused, rc = mc.mcCntlFeedHoldState(inst)
            if (Running) then -- We are running, so pause
                mc.mcSignalSetState(hRunLight, 0)       -- Make sure the RUN light is off
   	        mc.mcSignalSetState(hHoldLight, 1)      -- Turn the HOLD light on
                rc = mc.mcCntlFeedHold(inst)            -- Should this maybe be FeedHold()?
                mc.mcCntlSetLastError(inst, "Control Panel FEED HOLD")
            elseif (Paused) then -- We are paused, so stop
                mc.mcSignalSetState(hRunLight, 0)       -- Make sure the RUN light is off
   	        mc.mcSignalSetState(hHoldLight, 1)      -- Turn the HOLD light on
                CycleStop()
                mc.mcCntlSetLastError(inst, "Control Panel CYCLE STOP")
            else
                -- Spurious button press
                mc.mcCntlSetLastError(inst, "Not running or paused - IGNORE ME")
            end
        else
            mc.mcCntlSetLastError(inst, "Control Panel Feed Hold RELEASE")
        end
end
---------------------------------------------------------------
-- Control Panel Manual Spindle
---------------------------------------------------------------
function InputManualSpindle()
        -- Momentary pushbutton, so we get TWO signals with each button press:
        -- an "ON" and an "OFF"
        -- So check state and ignore the "OFF"
        local hSpindleButton
	local SpindleButtonState
	hSpindleButton, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT8)      -- TODO set correct signal
        SpindleButtonState, rc = mc.mcSignalGetState(hSpindleButton)
        if (SpindleButtonState == 1) then
	    -- We don't turn any lights on for manual spindle operation
	    -- but if we are here, let's make sure they are off
	    local hRunLight
   	    hRunLight, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1)  -- TODO set correct signal number
   	    local hHoldLight
   	    hHoldLight, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1) -- TODO set correct signal number
	    local hJogLight
	    hJogLight, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1)  -- TODO set correct signal number
            mc.mcCntlSetLastError(inst, "Control Panel Manual Spindle PRESS")
   	    mc.mcSignalSetState(hRunLight, 0)       -- Make sure the RUN light is off
   	    mc.mcSignalSetState(hHoldLight, 0)      -- Ditto HOLD
	    mc.mcSignalSetState(hJogLight, 0)       -- And JOG
            local hsig = mc.mcSignalGetHandle(inst, mc.OSIG_SPINDLEFWD)
            local spinstate = mc.mcSignalGetState(hsig)
            if (spindstate == 0) then         -- If spindle is off, turn it on
 	        mc.mcSignalSetState(hsig, 1)
                mc.mcCntlSetLastError(inst, "Control Panel Manual Spindle ON")
            else                              -- Otherwise, turn it off
                mc.mcSignalSetState(hsig, 0)
                mc.mcCntlSetLastError(inst, "Control Panel Manual Spindle OFF")
            end
        else
            mc.mcCntlSetLastError(inst, "Control Panel Manual Spindle RELEASE")
        end
end
----------------------------
-- We use MPG 7
local MachMpgNumberForPendant = 7
local PendantStepSize = 0.001 
local PendantDistanceX1 = PendantStepSize * 1    	-- Multiply by one (0.001)
local PendantDistanceX10 = PendantStepSize * 10    	-- Multiply by ten (0.01)
local PendantDistanceX100 = PendantStepSize * 100    	-- Multiply by one hundred (0.1)
-- Constants for readability
local UnmapMPG = -1         	-- Use this one for when Axis selector switch is set to OFF
local AxisNumber_X = 0       	-- Linear axis X 
local AxisNumber_Z = 2       	-- Linear axis Z 
---------------------------------------------------------------
-- Jog Speed/Enable Rotary Switch 
---------------------------------------------------------------
function PendantSpeedChange()
    local hX1
    local hX10
    local hX100
    -- Need to get current state of axis selector switch so we move the right axis
    local hAxis_X  -- X Axis Select Switch
    local hAxis_Z  -- Z Axis Select Switch
   
    local Step1
    local Step10
    local Step100
    local msg
   
    hX1, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT6)        -- Speed 0.001 TODO set correct signal
    Step1, rc = mc.mcSignalGetState(hX1)
   
    hX10, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT7)       -- Speed 0.01 TODO set correct signal
    Step10, rc = mc.mcSignalGetState(hX10)
   
    hX100, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT8)      -- Speed 0.1 TODO set correct signal
    Step100, rc = mc.mcSignalGetState(hX100)
   
    -- Jog Active Light handle
  
    local hJogLight
    hJogLight, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT1) -- TODO set correct signal
    -- Figure out which axis is active by reading the axis select switch
    hAxis_X, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT0)   -- If X is selected, activate X TODO set correct signal
    SelectAxis_X, rc = mc.mcSignalGetState(hAxis_X)
   
    hAxis_Z, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT2)   -- If Z is selected, activate Z TODO set correct signal
    SelectAxis_Z, rc = mc.mcSignalGetState(hAxis_Z)
    -- TODO - This should really check that we have X || Z, but not neither or both!
    if (SelectAxis_X == 1) then
        mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, AxisNumber_X)    -- Map the MPG to control the X Axis
        mc.mcCntlSetLastError(inst, "Jog Axis X Selected")     		-- Show a message in the Screen Set
       
    elseif (SelectAxis_Z== 1) then
        mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, AxisNumber_Z)    -- Map the MPG to control the Z Axis
        mc.mcCntlSetLastError(inst, "Jog Axis Z Selected")  		-- Show a message in the Screen Set
    end
  
    if (Step1 == 1) then
        mc.mcMpgSetInc(inst, MachMpgNumberForPendant, PendantDistanceX1 )
	mc.mcSignalSetState(hJogLight, 1)       			-- Turn Jog light on
        msg = "Jog Active X1 = " .. PendantDistanceX1
        mc.mcCntlSetLastError(inst, msg)  				-- Show a message in the Screen Set
    elseif (Step10 == 1) then
        mc.mcMpgSetInc(inst, MachMpgNumberForPendant, PendantDistanceX10)
	mc.mcSignalSetState(hJogLight, 1)       			-- Turn Jog light on
        msg = "Pendant Distance X10 = " .. PendantDistanceX10
        mc.mcCntlSetLastError(inst, msg)  				-- Show a message in the Screen Set
    elseif (Step100 == 1) then
        mc.mcMpgSetInc(inst, MachMpgNumberForPendant, PendantDistanceX100)
	mc.mcSignalSetState(hJogLight, 1)       			-- Turn Jog light on
        msg = "Pendant Distance X100 = " .. PendantDistanceX100
        mc.mcCntlSetLastError(inst, msg)  				-- Show a message in the Screen Set
    else
	-- If we got here, it means the one of the speed inputs changed, but none are active
	-- That means "JOG OFF"
	mc.mcMpgSetInc(inst, MachMpgNumberForPendant, 0 ) 		-- TODO Can we set the jog distance to 0?
	mc.mcSignalSetState(hJogLight, 0)       			-- Turn Jog light off
	mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, UnmapMPG )   	-- Unmap the MPG, so it won't control any axes
        mc.mcCntlSetLastError(inst, "Jog Handle Disabled")  		-- Show a message in the Screen Set
    end
   
end
---------------------------------------------------------------
-- The Pendant's Axis switch changed.
-- Need to handle this for when the axis switch is flipped while jogging is active
---------------------------------------------------------------
function PendantAxisChange()
 
    -- handles
    local hAxis_X 
    local hAxis_Z 
    local SelectAxis_X
    local SelectAxis_Z
    -- Before we do anything, we need to check if the jog handle is assigned to axis -1
    -- If it is, jog is DISABLED, so we do nothing (the act of enabling jog will read the axis switch)
    -- Otherwise we enable jog, which is BAD
    -- TODO - need a function to check which axis is assigned 
    -- This is a guess!
    local AxisState
    AxisState, rc = mc.mcMpgGetAxis(inst, MachMpgNumberForPendant)
    if (AxisState ~= UnmapMPG) then
        hAxis_X, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT0)   
        SelectAxis_X, rc = mc.mcSignalGetState(hAxis_X)
   
        hAxis_Z, rc = mc.mcSignalGetHandle(inst, mc.ISIG_INPUT2) 
        SelectAxis_Z, rc = mc.mcSignalGetState(hAxis_Z)
        -- Now actual axis Selection Switch processing code
        if (SelectAxis_X == 1) then
            mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, AxisNumber_X)    -- Map the MPG to control the X Axis
            mc.mcCntlSetLastError(inst, "Pendant Axis X Selected")  	    -- Show a message in the Screen Set
       
        elseif (SelectAxis_Z== 1) then
            mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, AxisNumber_Z)    -- Map the MPG to control the Z Axis
            mc.mcCntlSetLastError(inst, "Pendant Axis Z Selected")  	    -- Show a message in the Screen Set
    
        else
            -- This is a problem, because the axis select switch is one or the other
	    -- We have no high pin - so shut off jogging
            mc.mcMpgSetAxis(inst, MachMpgNumberForPendant, UnmapMPG )     	                -- Unmap the MPG, so it won't control any axes
            mc.mcCntlSetLastError(inst, "ABEND - no valid axis selected on control panel!")  	-- Show a message in the Screen Set
        end
     else
        mc.mcCntlSetLastError(inst, "Changed axis select while jog disabled - IGNORED") 
     end
end
-- Set jog state when the Screen is loaded by Mach4
PendantSpeedChange()