What's new

bobbydilley

Grand Master
Joined
Apr 29, 2018
Messages
543
Reaction score
591
Location
England
https://github.com/bobbydilley/JVSCore-Public

Lots of people where asking on the OpenJVS project for the opposite of what I'd done so this is the first release of my software which will allow you to use a JVS I/O board as a standard input device on Linux.

This is in very early stages, and currently only supports digital buttons. It'll be updated regularly and I will post here when its done.

This is an alternative to the JVS-Pac and only requires an RS485 converter, to work. This could be used on a Raspberry Pi for example to play emulators like Mame on a JVS cabinet.

I'm just posting here now to have a space to release updates, and will make a video / instructions when the software is finalised. I am to support every single function of the JVS I/O spec.
 
Have managed to getting it working with a Type 3 I/O, and have posted a video of it below.

https://www.youtube.com/watch?v=F_d3Dn7Dq5k

Unfortunately I cannot test the actual functionality as I have no buttons etc. to plug into the I/O at the moment - but hopefully getting the control panel from Let's Go Jungle soon so I'll be able to start work on it properly. The functionality is there to support ALL the input features of JVS so hopefully this will be a very versatile solution!
 
JVSCore now works nicely and is at: github.com/bobbydilley/JVSCore-Public

It's super easy to compile + install, and making an adapter should take about 5 minutes and cost about £10.

Supports:

- Any linux distrobution (probably)
- Analogue Controls
- Normal Button Controls
- Tested on Type 1 and Type 3, should work on anything.
- Running in the background as a systemd service, which will keep trying to reconnect to any JVS board you plug in.

I'm open to adding in functionality such as rotary / coin / screen touch position, but at the moment analogue+buttons are enough for my needs. If anyone wants anything specifically added just shout.

Heres a video of me playing a game with it:

https://youtu.be/wRQTcAfwV0M

Please ignore the strange lag with the controls. Mame seems to add in strange dampening effects on analogue joystick and I can't really work out how to turn them off.
 
Awesome work on this project, now the Pi 4 has enough beef to run Naomi games this could be real game changer!

I've been testing today on Raspbian Buster Lite on a Pi 4 and have run into an issue, not sure if it's the code or my cheap and cheerful Chinese RS-485 adaptor! I can get the code compiled and installed no problem and it runs just fine, however, it only seems to pick up the analog inputs. If I run evtest I can see I only have one device event number available which is zero, it constantly reports back analog input due to the zero settings for fuzz and deadzone so it shows that the Pi and IO are communicating OK. My IO board reports back with the capabilities and says it can support 2 players with digital buttons but it reports either a timeout, a checksum error or Error getting switches. Could it be a timing issue maybe? I'll grab a different type of adaptor, the same as you use in your video, see if that makes a difference.
 

Attachments

  • IMG-20191204-WA0018.jpg
    IMG-20191204-WA0018.jpg
    247.5 KB · Views: 189
  • IMG-20191204-WA0022.jpg
    IMG-20191204-WA0022.jpg
    189 KB · Views: 176
  • IMG-20191204-WA0024.jpg
    IMG-20191204-WA0024.jpg
    193.5 KB · Views: 203
Hey there!

You're probably right and I suspect it is something to do with the timing, I get some checksum errors sometimes on mine which i'm not sure how to fix. I think your adapter should be fine though!

You say you only see one device event number which is zero. This is correct, and that corresponds to that I/O you've got plugged in. You said you get lots of analogue reads reported back, I didn't realise that's what fuzz+deadzone where for, so i'll get that into the next version so hopefully it doesn't display millions of analogue reads all the time. Thanks for the heads up!

Things to try:

If you run evdev again, select event zero and then quickly press Ctrl + C it should display what capabilities have been reported to linux, such as switches etc. If you could take a picture of that, I can see how its managing the switches.

I can see you've manually run `sudo /usr/bin/jvscore`, when you do that, does it remain open forever, or does it error out and close? (btw, when you do run this command make sure you've stopped the service running in the background with `sudo systemctl stop jvscore`, or it'll take over the serial connection)

From the debugging info it looks like it should be reading the switches fine. For me, because the switches get mapped to the keyboard keys when I press certain switches on my cabinet it will type things into the terminal. Have you tried pressing all the switches on your cabinet, to see if any of them type anything? It's unlikely you'll see the switch reads while theres so much analogue traffic going on, if you type the following command it'll filter out just the switch reads:

`sudo evtest --grab /dev/input/event0 | grep EV_KEY`


Hopefully some of these might get us closer to the answer. Thanks so much for testing it out, and any other comments/feedback would be very much welcomed. I'll credit you on the github page for the fuzz+deadzone suggestion.
 
Thanks very much for the speedy response, I managed to test this morning and your filter suggestion worked :) I can see digital inputs appearing when I move the stick and press buttons which is great! I do get double inputs on the stick so I think the debounce setting might need increasing and also I think I only get keypresses for Start and Coin but not the player buttons. I'll double check my cab wiring later just to make sure it's not a physical issue but this is just amazing! Would you mind if I fork your code and have a play around? I've written python based uinput controllers so I can see how the code is working, I'd like to change the inputs to mame defaults too. Also is it possible to add the debounce, fuzz and deadzone settings to the config file?

Edit: just noticed I'm being an idiot, the evtest shows input pressed, input released, not a double press!

You can see I tried jstest in the photo attached, I just get a single analog controller with no digital inputs, is that expected? Also, am I right in thinking this section of code is where the button inputs are being defined, using consecutive numbers from input-event-codes.h?

ioctl(fd, UI_SET_EVBIT, EV_KEY);
for (int i = 0; i < capabilities.switches * capabilities.players; i++)
{
ioctl(fd, UI_SET_KEYBIT, 2 + i);
}

Output of evtest:

Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x8371 product 0x3551 version 0x1
Input device name: "SEGA ENTERPRISES,LTD.;I/O 838-13683B ;Ver1.07;99/06"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 2 (KEY_1)
Event code 3 (KEY_2)
Event code 4 (KEY_3)
Event code 5 (KEY_4)
Event code 6 (KEY_5)
Event code 7 (KEY_6)
Event code 8 (KEY_7)
Event code 9 (KEY_8)
Event code 10 (KEY_9)
Event code 11 (KEY_0)
Event code 12 (KEY_MINUS)
Event code 13 (KEY_EQUAL)
Event code 14 (KEY_BACKSPACE)
Event code 15 (KEY_TAB)
Event code 16 (KEY_Q)
Event code 17 (KEY_W)
Event code 18 (KEY_E)
Event code 19 (KEY_R)
Event code 20 (KEY_T)
Event code 21 (KEY_Y)
Event code 22 (KEY_U)
Event code 23 (KEY_I)
Event type 3 (EV_ABS)
Event code 0 (ABS_X)
Value 16
Min 0
Max 255
Event code 1 (ABS_Y)
Value 16
Min 0
Max 255
Event code 2 (ABS_Z)
Value 16
Min 0
Max 255
Event code 3 (ABS_RX)
Value 16
Min 0
Max 255
Event code 4 (ABS_RY)
Value 16
Min 0
Max 255
Event code 5 (ABS_RZ)
Value 16
Min 0
Max 255
Event code 6 (ABS_THROTTLE)
Value 16
Min 0
Max 255
Event code 7 (ABS_RUDDER)
Value 16
Min 0
Max 255

I have a suspicion I know what is going on, I've tested all player 1 and 2 inputs plus the service and test buttons, here is the only EV_KEY output:

pi@raspberrypi:~ $ sudo evtest --grab /dev/input/event0 | grep EV_KEY
Event type 1 (EV_KEY)
Event: time 1575569148.450595, type 1 (EV_KEY), code 11 (KEY_0), value 1
Event: time 1575569148.599926, type 1 (EV_KEY), code 11 (KEY_0), value 0
Event: time 1575569149.286354, type 1 (EV_KEY), code 10 (KEY_9), value 1
Event: time 1575569149.375928, type 1 (EV_KEY), code 10 (KEY_9), value 0
Event: time 1575569151.973548, type 1 (EV_KEY), code 15 (KEY_TAB), value 1
Event: time 1575569152.092980, type 1 (EV_KEY), code 15 (KEY_TAB), value 0
Event: time 1575569152.449882, type 1 (EV_KEY), code 13 (KEY_EQUAL), value 1
Event: time 1575569152.598522, type 1 (EV_KEY), code 13 (KEY_EQUAL), value 0
Event: time 1575569152.895723, type 1 (EV_KEY), code 14 (KEY_BACKSPACE), value 1
Event: time 1575569153.014678, type 1 (EV_KEY), code 14 (KEY_BACKSPACE), value 0
Event: time 1575569153.252335, type 1 (EV_KEY), code 12 (KEY_MINUS), value 1
Event: time 1575569153.341406, type 1 (EV_KEY), code 12 (KEY_MINUS), value 0
Event: time 1575569155.243712, type 1 (EV_KEY), code 17 (KEY_W), value 1
Event: time 1575569155.332949, type 1 (EV_KEY), code 17 (KEY_W), value 0
Event: time 1575569172.043873, type 1 (EV_KEY), code 9 (KEY_8), value 1
Event: time 1575569172.402207, type 1 (EV_KEY), code 9 (KEY_8), value 0
Event: time 1575569173.297450, type 1 (EV_KEY), code 16 (KEY_Q), value 1
Event: time 1575569173.566187, type 1 (EV_KEY), code 16 (KEY_Q), value 0

As you can see all codes from 17->9 are reported which is the second byte of input data of 4 but the others are ignored - if I've read this bit of code right:

for (int i = 0; i < 2 * capabilities.players; i++)
{
for (int j = 7; 0 <= j; j--)
{
emit(fd, EV_KEY, 2 + ( i * 8 ) + j, ( switches[ i ] >> j ) & 0x01);
}
}

I'll keep testing and let you know if I manage to suss where the issue lies
 

Attachments

  • IMG-20191205-WA0000.jpg
    IMG-20191205-WA0000.jpg
    155.2 KB · Views: 168
  • IMG-20191205-WA0001.jpg
    IMG-20191205-WA0001.jpg
    250.1 KB · Views: 175
  • IMG-20191205-WA0002.jpg
    IMG-20191205-WA0002.jpg
    251.9 KB · Views: 161
Last edited:
Hey again!

Thanks for all the debugging work - you're probably right, that code probably only uses the first byte. I've only got a Let's Go Jungle setup to run it on which doesn't include many buttons.

I suspect `jstest` only looks for buttons from a joystick. I've mapped all the switches to keyboard keys, and jstest probably doesn't test for those. I'd be more than happy to switch them up to some proper joystick buttons in the code, and you mention that you know what the defaults for mame are which would help.

It should be easy enough to create an array of which keys are defined in which order, and then still use a loop to reference them.

For example: `int keysToMap[] = {BTN_A, BTN_0, BTN_B, BTN_9...}` etc.

Please feel free to fork, and i'll merge back in if you make any progress. I'll have a little look tonight if I've got time to see what might be going on.

I'll definately add the fuzz/deadzone values to the config file. Do you think we'll need individual values for each analogue channel, or will one global value suffice?


----

Just had a look at the code in the section you sent:


It goes from i = 0 to 2 * capabilities.players.

I think it should go from i = 0 to switchBytes * capabilities.players.

Think I just missed it when I was refactoring - give that a go and tell me if that open up all the buttons for you!
 
Last edited:
Thanks for the support with this :)

I've updated that variable but I think it still gives the same end result, the switchbytes are still 2 based on the calculation 11/8 quot=1 rem=1. In the jvs.c code is the switchbytes variable updated to reflect the number of players? I can't quite work out the logic!

Edit: so it looks like maybe it's only pulling back 2 bytes instead of 4, do we need to multiply switchbytes by capabilities.players before GetSwitches?
 
Yeah I see what you mean. 1 Players worth of 11 buttons would be 2 bytes, and we're timing that by the amount of players so its correctly trying to read through 4 bytes of data.

the getSwitches(char *switches, int players, int bytes) function looks to be correctly called with 2 players, and 2 bytes each. So I'm not really sure what its not doing.

Something to try:

Right under the emit function call put: printf("%d ", (switches >> j) & 0x01);
At the end of the outer loop (the one that deals with i) put a printf("\n"); to make it go down to a new line.
If you want at the end of the inner loop (the one that deals with j) put a printf(" : "); and that will help to seperate each byte of data.

You should then get an output of 24 0/1s which will better help you see which keys aren't working. I'm assuming one of the bytes will be completely zero and we can work out which one isn't working properly.
 
Ok I tested and am now getting a stream of 4 blocks of 8 bits. Comparing the button key outputs to the byte readout I can see that the data is all there in the byte stream but not in the outputs, only the first 2 bytes worth. Player 1 button 3 is on the third byte and gives you a 1 in the byte stream (first bit of byte 3) but no key output. The player 2 outputs are on the fourth byte but again, no key output. Interestingly player 2 button 3 must be on a fifth byte that's not being read at all! I'll upload a YouTube vid to better explain.

YouTube Video

So possibly an issue with the emit command? All the data seems to be there
 
Last edited:
Thanks for the vid!

The system buttons are clearly a problem, and I think you're right I need to be reading in an extra byte for each one.

I've created a branch called Develop, and i'll be adding that change to there shortly. It's nice to know that the program is getting the data correctly, and it's just the way I'm sending it out. Should hopefully be an easy fix!

RE the coin, are you testing it by putting a coin in the slot, or do you have a button that simulates that? Unforunately the 'coin' part of JVS is a bit more complex than just a button, and it actually has various functions for increment+decrement coins which i've not yet implemented. You'll probably have to use the service button to coin up for now, and then i'll attempt to get some coin action going once we've got this fixed.

-- Edit

Have pushed the code to add the 8 extra button at the start.

That should mean that 5 sets of 8 come out now, so would be good if you could check if all the buttons at least report for each side. Next is to find out why it's not reporting all of them properly to linux.

-- Edit Again

Just found a bug that could have been the problem. I told linux that we've got capabilities.switches * capabilities.players. This means that if we've got 11 buttons and 2 players, we output we've got 22 possible buttons.

When we read the bytes in, for 11 switches we would read (2*8) 16 bits. This means we loose report out an extra 5 switches that don't exist which push up the remaining ones. So we'd be reporting the spaces for 32 bits (just for the original swtiches), when 10 of those don't actually exist. Have just pushed to the develop branch, and i'm hoping this will fix all your problems :D
 
Last edited:
Ah, yes you're right, it needs 5v to the coin counter pin to simulate the counter being present, mine is just a push button.

Can't spot the issue, but should this line:

for (int i = 0; i < 2 * capabilities.players; i++)


Read

for (int i = 0; i < switchBytes * capabilities.players; i++)
 
Sorry I've been editing the previous message so the threads have possibly got crossed.

I've you look at the branch 'Develop' i've made all the changes I think are required to fix everything.

https://github.com/bobbydilley/JVSCore-Public/tree/Develop

On your raspberry pi, if you type in:

`git checkout Develop`

It'll move you onto the Develop branch, and you can re-compile and install the software, and see if that fixes anything. It's now got fuzz defined in the config file as well, so if you don't want to see the analogue inputs in evtest, you can turn that up really high.
 
OK, I compiled and ran the code, it's now reporting back 12 bytes (boxed in red) and the missing player 2 button 3 is now there and working, oddly, the following byte has inputs stuck on - not sure what these are!

In terms of the evtest, I now don't get the test button, up, down or the player 1 start button outputting a key so less than before I'm afraid ...
 

Attachments

  • bytestream.jpg
    bytestream.jpg
    28.4 KB · Views: 155
Ohh! Sorry made loads of silly mistakes there, have updated the code again on the Develop branch. If you could have another try that would be great!
 
Yesss!! All working apart from player 2 button 3, presumably it disappears off onto the next byte. Fantastic work!

Edit - confirmed detected properly on the last byte of data but no key output

Would changing "for (int i = 0; i < switchBytes * capabilities.players + 1; i++)" to "for (int i = 0; i <= switchBytes * capabilities.players + 1; i++)" fix it?

Edit: No!

Edit 2: But changing "for (int i = 0; i < (8 * switchBytes) * capabilities.players + 1; i++)" to "for (int i = 0; i < (8 * switchBytes) * capabilities.players + 8; i++)" has fixed it! all working!!

Many thanks again! :)
 
Last edited:
You should get 5 bytes now, with the service+test at the top, 2 bytes for p1 and 2 bytes for p2.

Don't really know why P2B3 wouldn't work? Does it come up in the list if you add the print statements?
 
Back
Top