Skip to content

Instantly share code, notes, and snippets.

@cyberluke
Last active August 16, 2022 10:07
Show Gist options
  • Save cyberluke/baaadd29bd01fcd6d6e47de3569c3482 to your computer and use it in GitHub Desktop.
Save cyberluke/baaadd29bd01fcd6d6e47de3569c3482 to your computer and use it in GitHub Desktop.
FreePIE_Thrustmaster_HOTAS_Gameport_Win10.py - Mark II Weapon System converting PS/2 keyboard input to vJoy joystick device (need to create vJoy joystick manually: in vJoy configuration check: X,Y,Z,Rx,Ry,Rz,Slider,Slider2 and POV select 1 - continuous), number of buttons: 8
if starting:
import time
import math
#The following is the tweakaxis function. Don't change this unless you know how to program. Call on this function in the Axis Rebinds section.
def tweakaxis(input, input_range_min, adjusted_center, input_range_max, dband):
if input >= adjusted_center:
return filters.ensureMapRange(input, adjusted_center + dband, input_range_max, 0, 1000)
elif input <= adjusted_center:
return filters.ensureMapRange(input, input_range_min, adjusted_center - dband, -1000, 0)
else:
return 0
#The tweakaxis function's variables explained:
#input:-------------This specifies the input (usually a real joystick axis) to be modified.
#input_range_min:---The value of the input to map to the tweaked output's full minimum. Use -1000 for an unchanged endpoint on conventional joysticks.
#adjusted_center:---The value of the input to map to the tweaked output's center. Assign a new center point to your joystick's axis with this value.
#input_range_max:---The value of the input to map to the tweaked output's full maximum. Use 1000 for an unchanged endpoint on conventional joysticks.
#dband:-------------Deadband. The distance that you must move the input away from adjusted_center before the smallest value is output.
#Tips:
#input_range_min and _max can be changed to alter the effective range of an axis on a physical device.
#For example, it can be used to halve the stick travel distance for the full range of outputs by using a _min of -500 and a _max of 500.
#If making asymmetrical changes to the input_range values, remember to consider whether adjusted_center needs to bisect those values.
#Using values for these vars with absolute value greater than 1000 (again, for most sticks) will result in more precision by sacrificing access to the output values at the extremities.
#tweakaxis() is meant to be composed, including with itself. The order matters greatly. The true power of the script lies here.
#Enclose every set of functions in this before setting a vJoy axis equal to it:
def vJR(input):
return filters.ensureMapRange(input, -1000, 1000, -vJoy[0].axisMax, vJoy[0].axisMax)
#Curve functions:
#Basic x^n curve:
def powcv(input, curvepower, min = -1000, max = 1000):
if input >= 0:
return filters.ensureMapRange(math.pow(input, curvepower), 0, math.pow(max, curvepower), 0, max)
else:
return filters.ensureMapRange(-math.pow(-input, curvepower), -math.pow(-min, curvepower), 0, min, 0)
#Fancy -((1-x)^n)+1 curve, made origin-symmetric:
#Use 0 << n << 1 for best results, with small f''(x) for small x and large f''(x) for large x.
def revrootcv(input, curvepower, min = -1000, max = 1000):
if input >= 0:
return filters.ensureMapRange(1-math.pow(1-filters.ensureMapRange(input, 0, max, 0, 1), curvepower), 0, 1, 0, max)
else:
return filters.ensureMapRange(-1+math.pow(1-filters.ensureMapRange(-input, 0, -min, 0, 1), curvepower), -1, 0, min, 0)
#Master-controlled scaling for inputs:
#The variable limits created converge on the center of whichever function is directly inside it.
#"master" switch made to easily determine which control to use.
def mscale(input, master = 0):
if master == 0: #Positional master
scalevalue = filters.ensureMapRange(-joystick[2].x, 0, 1000, 0.15, 1)
if joystick[2].x > 990:
scalevalue = 0
return input * scalevalue
elif master == 1: #Rotational master
scalevalue = filters.ensureMapRange(joystick[2].zRotation, -990, 990, 0, 1)
return input * scalevalue
else:
return 0
#Change axis_mult if 'Windows output: vJoy' axes have the wrong range of motion.
# (They should match the correspondingly bound values of
# 'Windows output: Physical' 1 and 2 exactly.)
axis_mult = (vJoy[0].axisMax / 1000)
t0 = time.clock()
#Joystick button to keyboard button variable function
def jkey(j_index, j_button, keybind):
if joystick[j_index].getDown(j_button):
keyboard.setKeyDown(keybind)
else:
keyboard.setKeyUp(keybind)
#Joystick button to keyboard button variable function
def keyj(Key, j_button):
if keyboard.getKeyDown(Key):
vJoy[0].setButton(j_button, 1)
else:
vJoy[0].setButton(j_button, 0)
def keyCodeToNumber(key):
if (key == Key.D1):
return -16535
if (key == Key.D2):
return -12258
if (key == Key.D3):
return -8192
if (key == Key.D4):
return -4096
if (key == Key.D5):
return 0
if (key == Key.D6):
return 4096
if (key == Key.D7):
return 8192
if (key == Key.D8):
return 12258
if (key == Key.D9):
return 16535
#Joystick button to keyboard button variable function
def keyaxis(key):
if keyboard.getKeyDown(key):
vJoy[0].z = keyCodeToNumber(key)
#Joystick button to vJoy button variable function
def jvjb(j_index, j_button, vjoy_button):
if joystick[j_index].getDown(j_button):
vJoy[0].setButton(vjoy_button, 1)
else:
vJoy[0].setButton(vjoy_button, 0)
#Axis rebinds
#Adding 1 before multiplying by axis_mult seems to compensate for
# a one step offset in the vJoy driver itself.
vJoy[0].x = (joystick[0].x + 1 ) * axis_mult
vJoy[0].y = (joystick[0].y + 1 ) * axis_mult
#vJoy[0].z = (joystick[0].zRotation + 1 ) * axis_mult
#vJoy[0].slider = (joystick[2].sliders[0] * -1 + 1 ) * axis_mult
#vJoy[0].dial = (joystick[2].sliders[0] * -1 + 1 ) * axis_mult
if (joystick[2].zRotation != 1000):
#vJoy[0].rz = (joystick[2].zRotation * -1 + 1 ) * axis_mult
vJoy[0].rz = 10*vJR(mscale(tweakaxis(joystick[2].zRotation, -1000, 0, 0, 1)))
elif (joystick[2].sliders[0] != 1000):
vJoy[0].rz = -10*vJR(mscale(tweakaxis(joystick[2].sliders[0], -1000, 0, 0, 1)))
else:
vJoy[0].rz = 0
vJoy[0].setAnalogPov(0, joystick[0].pov[0])
joystick[0].pov[0]=0
joystick[0].pov[1]=0
joystick[1].pov[0]=0
joystick[1].pov[1]=0
#Button rebinds
jvjb(0, 0, 0)
jvjb(0, 1, 1)
jvjb(0, 2, 2)
jvjb(0, 3, 3)
jvjb(0, 4, 4)
jvjb(0, 5, 5)
jvjb(0, 6, 6)
jvjb(0, 7, 7)
keyaxis(Key.D1)
keyaxis(Key.D2)
keyaxis(Key.D3)
keyaxis(Key.D4)
keyaxis(Key.D5)
keyaxis(Key.D6)
keyaxis(Key.D7)
keyaxis(Key.D8)
keyaxis(Key.D9)
#FreePIE "Watch" tab joystick state monitors
#System values for vJoy simulated device
diagnostics.watch(joystick[2].sliders[0])
diagnostics.watch(joystick[2].zRotation)
diagnostics.watch("Windows output: vJoy")
diagnostics.watch(joystick[0].getDown(0))
diagnostics.watch(joystick[0].getDown(1))
diagnostics.watch(joystick[0].getDown(2))
diagnostics.watch(joystick[0].getDown(3))
diagnostics.watch(joystick[0].getDown(4))
diagnostics.watch(joystick[0].getDown(5))
diagnostics.watch(joystick[0].getDown(6))
diagnostics.watch(joystick[0].getDown(7))
diagnostics.watch(joystick[0].getDown(8))
diagnostics.watch(joystick[0].getDown(9))
diagnostics.watch(joystick[0].getDown(10))
diagnostics.watch(joystick[0].getDown(11))
diagnostics.watch(joystick[0].getDown(12))
diagnostics.watch(joystick[0].getDown(13))
diagnostics.watch(joystick[0].getDown(14))
diagnostics.watch(joystick[0].getDown(15))
diagnostics.watch(joystick[0].sliders[0])
diagnostics.watch(joystick[0].sliders[1])
diagnostics.watch(joystick[0].x)
diagnostics.watch(joystick[0].y)
diagnostics.watch(joystick[0].z)
#diagnostics.watch(joystick[0].xRotation)) FreePIE does not support these two values
#diagnostics.watch(joystick[0].yRotation)) EDIT: Jan 2015: It does now!
diagnostics.watch(joystick[0].zRotation)
diagnostics.watch(joystick[0].pov[0])
diagnostics.watch(joystick[0].pov[1])
#vJoy driver internal values
# (axes only, vJoy driver button values are not readable in FreePIE)
diagnostics.watch("vJoy driver values")
diagnostics.watch(vJoy[0].x)
diagnostics.watch(vJoy[0].y)
diagnostics.watch(vJoy[0].z)
diagnostics.watch(vJoy[0].rx)
diagnostics.watch(vJoy[0].ry)
diagnostics.watch(vJoy[0].rz)
diagnostics.watch(vJoy[0].slider)
diagnostics.watch(vJoy[0].dial)
#Physical joystick 1
diagnostics.watch("Windows output: Physical 1")
diagnostics.watch(joystick[1].getDown(0))
diagnostics.watch(joystick[1].getDown(1))
diagnostics.watch(joystick[1].getDown(2))
diagnostics.watch(joystick[1].getDown(3))
diagnostics.watch(joystick[1].getDown(4))
diagnostics.watch(joystick[1].getDown(5))
diagnostics.watch(joystick[1].getDown(6))
diagnostics.watch(joystick[1].getDown(7))
diagnostics.watch(joystick[1].sliders[0])
diagnostics.watch(joystick[1].x)
diagnostics.watch(joystick[1].y)
diagnostics.watch(joystick[1].zRotation)
diagnostics.watch(joystick[1].pov[0])
#Script execution time tracker
totaltime = time.clock() - t0
diagnostics.watch(totaltime)
""""""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment