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

Feature Request: Mapping POV Hat in vJoySF #43

Closed
Hyratel opened this issue Dec 11, 2020 · 11 comments
Closed

Feature Request: Mapping POV Hat in vJoySF #43

Hyratel opened this issue Dec 11, 2020 · 11 comments

Comments

@Hyratel
Copy link

Hyratel commented Dec 11, 2020

I was not able to find any mention, and I think it would be very useful to be able to map inputs in vJoySF to vJoy hat switch inputs. it seems to be the one thing substantially missing in the features of the main program, unless I've overlooked some functionality

@Cleric-K
Copy link
Owner

You are correct - there is no such feature at this time.

I considered hats at the time of writing but there are many different ways one can map axes/buttons to hats. For example, we can have buttons for each direction. Or we can have two X/Y axes in hat space where the angle to the XY point is measured and the direction of the hat determined accordingly.
In order not to limit the user in only one specific case it was necessary to make quite versatile mapping control that could probably take input from several channels or other mappings. Complexity was rising exponentially. For that reason I've put that aside at the time. It was way too much work and I wasn't sure if it was worth it. For the several years of vjsf life you are the first person to ask about hats.

Probably the easiest way (from my perspective as a developer) to implement this feature would be to add the support in the Scripting module. There one would be free to use whatever raw data one likes in order to determine the hat position.

Another thing I haven't investigated is what support for hats the different virtual joystick drivers have. I'm pretty sure vJoy has support but not sure about xbox and linux.

In any case right in this moment I physically don't have the time for this. Maybe beginning of next year I'll look into it. If there's some movement with this I'll let you know.

Best~

@Hyratel
Copy link
Author

Hyratel commented Dec 14, 2020

As best I understand, the most minimal hat implementation is the 8-way on 4 buttons, passing angle-heading or -1 to the vJoy device. it's implemented such that most games parse-as four buttons. and the D-pad on xbox is a Hat, programatically

and, very understandable re: 'don't have time'. just putting some thoughts up for consideration

wandering thoughts:
I've played with Arduino Leonardo/HID Joystick, and parsing a hat switch uses one analog pin/axis of electrical input, or four digital pins, or 4 digital pins of a shift register, depending on the era and specifics of the joystick. as an analog input, it has to be able to handle 9 unique resistive states: open/ N/E/S/W, NE/SE Etc. but it does not end up being a linear relation: two resistors in parallel are less than either so your half-headings end up all over the place. However, passing the result back to the computer uses a signed int, with [-1] for 'open' or the angle-heading. Windows DI Joystick Subsystem can handle continuous hat but most games can't, as they treat it more like two digital axes, or four discrete buttons

just went and checked, vJoy has support for up to four 8way-or-Continuous Hats, which is equal to Windows DirectInput HID handling per joystick device

@Cleric-K
Copy link
Owner

Thanks for the info. Yeah, this only confirms that probably the best way would be to implement HAT API interface in the script module and from there anyone to use however he likes. Otherwise it's just too many variants and a GUI control will become extremely complicated.

@Cleric-K
Copy link
Owner

Are you interested to experiment with Lua scripting? I can implement hat API relatively quickly but it will be up to you to test it.

@Hyratel
Copy link
Author

Hyratel commented Dec 17, 2020

I think so. throwing code at an arduino is easy enough, so that part's a nonissue. I've never really dug into Lua so this would be a good chance to cut my teeth on it

@Cleric-K
Copy link
Owner

Here's a custom build:
vJoySerialFeeder.zip

Well, I wouldn't say you need to dig inside Lua at all. You just need to call single function:

function update()
    VJoy.SetDiscPov(1, Channel(1))
    -- or
    VJoy.SetContPov(1, Channel(1))
end

There are two kinds of hats in vJoy driver - Discrete and Continuous. Discrete are four directions only. You set them with SetDiscPov(povnum, value). povnum is the hat (from 1 to 4). Value is:
0 North (forward)
1 East (right)
2 South (backwards)
3 West (Left)
-1 Neutral
(from http://vjoystick.sourceforge.net/site/includes/SDK_ReadMe.pdf)

For SetContPov(povnum, value) povname is the same, while value can be any number in degrees. 0 is North/Up, 90 is East/Right, etc.
If value is negative number hat goes to neutral.

Channel() is vjsf function that returns the raw value from the serial channel. It is up to you how you're gonna implement the whole thing. If you are more comfortable in Arduino you can prepare the correct value there and simply give it to vjoy like in the example above. Otherwise you'll need to transform the value in Lua.

If you need to convert two axis system to continuous hat, maybe something like:

    -- assuming channels vary between 0 and 1023
    -- map [0; 1023] -> [-1; 1]
    x = (Channel(1)/1023 - 0.5) * 2
    y = (Channel(2)/1023 - 0.5) * 2
    d = math.sqrt(x*x + y*y) -- distance to (0,0)
    
    if d < .1 then
        -- below certain threshold - move to neutral
        VJoy.SetContPov(1, -1)
    else
        sn = y/d
        cs = x/d
        -- vjoy angle increases in CW direction and 0 is UP, while mathematical degrees increase in CCW direction and 0 is RIGHT
        deg = deg = (90 - 180*math.atan(sn, cs)/math.pi ) % 360
        VJoy.SetContPov(3, deg)
    end

If you need any help just write.

@Hyratel
Copy link
Author

Hyratel commented Dec 18, 2020

I've got it working (oof, all-nighter) and the SDK Docs are actually wrong: SetContPov() doesn't take deg*100 as said in the SDK, but just deg

praQb3m 1

-- place initialization code here
local outputdelaydura = 500
local outputdelaytick = 0
function update()
heading = {
    -1,
    0,  
    45, 
    90,  
    135, 
    180, 
    225, 
    270, 
    315  
}
 bitmask = {
    0x0,
    0x1,
    0x3,
    0x2,
    0x6,
    0x4,
    0xC,
    0x8,
    0x9
}
    -- [place code to be executed on every update here --]
    local bitRead = bit32.band(0xF,bit32.rshift(Channel(8),0)) --bit32.band(0xF000,Channel(1))
    
    for headingIndex = 1,9
        do
            --print(headingIndex,headings[headingIndex],string.format('%x',bitmask[headingIndex]),bitmask[headingIndex])
            if( bitRead == bitmask[headingIndex]) then
                VJoy.SetContPov(1,heading[headingIndex])
                if outputdelaytick  == outputdelaydura then -- reduce console spam
                print(heading[headingIndex])
            end
                break
            end
        end
            if outputdelaytick == outputdelaydura -- reduce console spam
        then
        print(bitRead, string.format('%x',bitRead))
        outputdelaytick    = 0
    end
     outputdelaytick = outputdelaytick + 1 
end

(my feeder hardware is actually not Arduino U-series (16/32u) but a Cypress PSoC with discrete USB-serial adapter. I was not able to get VJSF to listen to the Arduino Pro Micro (Same Chip As Leonardo, 32U4)- it would read one Frame, and then timeout, I can raise that as a separate Issue if you'd like me to)

Hot Tip: the Windows Built-In Game Controller Observer halts UI Updates when it's lost-focus, but Pointy's Joystick Test does not, so you can watch your results in real time

@Cleric-K
Copy link
Owner

Great job!
Sorry if you have lost much time with the degrees. The vJoy driver really accepts 0 - 35999 and 0xffffffff for neutral. Because I had to convert the value anyway, I decided to make it easier on the Lua side and input there pure decimal degrees instead of working with the raw integers. The decimal value is the in converted to uint in C#.

I'm glad you got it working.

About the pro micro - I don't know what that could be. You can test with different software to see if the data looks ok. Like : #3 (comment) (except you need 115200 8-n-1)

@Cleric-K
Copy link
Owner

btw vJoy comes with its own vJoy monitor (look in the program group) that also works in background. It shows the continuous pov as dot moving on a circle.

@Hyratel
Copy link
Author

Hyratel commented Dec 19, 2020

It looks like the version with Lua-side POV hat support is good to go.

Cleric-K added a commit that referenced this issue Mar 16, 2022
@Cleric-K
Copy link
Owner

Hi after a long time this has been added in a release. Thanks for the help!

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants