RetroPie forum home
    • Recent
    • Tags
    • Popular
    • Home
    • Docs
    • Register
    • Login
    Please do not post a support request without first reading and following the advice in https://retropie.org.uk/forum/topic/3/read-this-first

    Analog Joystick

    Scheduled Pinned Locked Moved Help and Support
    pspiothermodpspjoystickanalog stick
    10 Posts 4 Posters 4.2k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • adamspcA
      adamspc
      last edited by adamspc

      Hey everyone. I'm trying to put the finishing touches on my PSPi, but I need some help.

      I'm using an MCP3002 analog/digital converter. I've got the OS correctly reading the values (not easy because spidev could not be installed until I did a full reinstall of python 2.7.9), and I need to know how to get it working in games. I've searched everywhere for this answer and cannot find it. I hacked some code together, and right now the python script below grabs the values from the ADC and uses uinput to send the values to ABS_X and ABS_Y. I know the ABS method was a long shot, but it was worth a try.

      I know that the most recent version of Retropie asks for analog up/down/left/right during configuration, so something is obviously built in. Can anyone tell me how to connect the dots? I have no hair left to pull out.

      #!/usr/bin/python
      
      import spidev
      import time
      import os
      import uinput
      
      DEBUG = 0
      
      spi = spidev.SpiDev()
      spi.open(0,0)
      spi.max_speed_hz = 100000
      
      def get_adc(channel):
              if ((channel > 1) or (channel < 0)):
                      return -1
      
              r = spi.xfer2([1,(2+channel)<<6,0])
              ret = ((r[1]&31) << 6) + (r[2] >> 2)
              return ret
      
      device =uinput.Device([uinput.ABS_X+(0,1023,0,0),
                            uinput.ABS_Y+(0,1023,0,0),
                            ])
      
      
      
      
      joy_x=1
      joy_y=2
      
      #!/usr/bin/python
      
      import spidev
      import time
      import os
      import uinput
      
      DEBUG = 0
      
      spi = spidev.SpiDev()
      spi.open(0,0)
      spi.max_speed_hz = 100000
      
      def get_adc(channel):
              if ((channel > 1) or (channel < 0)):
                      return -1
      
              r = spi.xfer2([1,(2+channel)<<6,0])
              ret = ((r[1]&31) << 6) + (r[2] >> 2)
              return ret
      
      device =uinput.Device([uinput.ABS_X+(0,1023,0,0),
                            uinput.ABS_Y+(0,1023,0,0),
                            ])
      
      
      
      
      joy_x=1
      joy_y=2
      
      while True:
        
          joy_x_value=ReadChannel(joy_x)
             
          device.emit(uinput.ABS_X,joy_x_value,syn=False)
      
          joy_y_value=ReadChannel(joy_y)
             
          device.emit(uinput.ABS_Y,joy_y_value)    
          time.sleep(0.020)

      https://www.othermod.com

      dankcushionsD 1 Reply Last reply Reply Quote 0
      • dankcushionsD
        dankcushions Global Moderator @adamspc
        last edited by

        @adamspc said in Analog Joystick:

        I know that the most recent version of Retropie asks for analog up/down/left/right during configuration, so something is obviously built in.

        so is it getting picked up here?

        I need to know how to get it working in games.

        in retroarch cores there's an analog to digital configuration option that will work if your answer to my previous question is 'yes'. check out https://github.com/retropie/retropie-setup/wiki/Configuration-Editor

        adamspcA 1 Reply Last reply Reply Quote 0
        • adamspcA
          adamspc @dankcushions
          last edited by adamspc

          @dankcushions
          It's not.

          I'm using retrogame, so when I press a button to configure input it says its using keyboard as an input. I then configure the regular buttons and it gets to analog, and moving the stick around does nothing.

          For clarification, so far I've only managed to print the current ACD values and then use uinput to send those values to ABS_X/Y. That's as far as I've made it and I'm not even sure ABS_X/Y is the right thing to do.

          https://www.othermod.com

          dankcushionsD 1 Reply Last reply Reply Quote 0
          • dankcushionsD
            dankcushions Global Moderator @adamspc
            last edited by

            @adamspc so when you say the OS can 'see' it, what do you mean by that? it appears as a js device in jstest?

            adamspcA 1 Reply Last reply Reply Quote 0
            • adamspcA
              adamspc @dankcushions
              last edited by

              @dankcushions the OS is communicating with the ADC and receiving the values using the Python file. The only info I could find was one person saying use uinput and ABS, so that's as far as I got. I havent used jtest but im researching it now. Im just trying to connect the dots on getting this configured as a joystick. I know it's not that something is wrong with it. I just can't find the information.

              https://www.othermod.com

              dankcushionsD 1 Reply Last reply Reply Quote 0
              • dankcushionsD
                dankcushions Global Moderator @adamspc
                last edited by

                @adamspc

                http://thiemonge.org/getting-started-with-uinput

                uinput is a linux kernel module that allows to handle the input subsystem from user land. It can be used to create and to handle input devices from an application. It creates a character device in /dev/input directory. The device is a virtual interface, it doesn't belong to a physical device.

                looks to me like this wouldn't be visible to ES or retroarch which are looking for keyboard or joystick devices. i think you'd need to create your own driver to translate like http://blog.petrockblock.com/2014/06/01/xarcade2jstick/

                adamspcA 1 Reply Last reply Reply Quote 0
                • adamspcA
                  adamspc @dankcushions
                  last edited by adamspc

                  @dankcushions I appreciate the responses. My hope was that someone in the forum had already done what I'm attempting and I could get a shortcut to the solution. I'm continuing to research and I'll post the solution once I find it (or create it). I'm digging into some slightly different code now that I found here.

                  """ rpi-gpio-jstk.py by Chris Swan 9 Aug 2012
                  GPIO Joystick driver for Raspberry Pi for use with 80s 5 switch joysticks
                  based on python-uinput/examples/joystick.py by tuomasjjrasanen
                  https://github.com/tuomasjjrasanen/python-uinput/blob/master/examples/joystick.py
                  requires uinput kernel module (sudo modprobe uinput)
                  requires python-uinput (git clone https://github.com/tuomasjjrasanen/python-uinput)
                  requires python RPi.GPIO (from http://pypi.python.org/pypi/RPi.GPIO/0.3.1a)
                  for detailed usage see http://blog.thestateofme.com/2012/08/10/raspberry-pi-gpio-joystick/
                  Changes
                  19 Aug 2012 - inputs set to use internal pull ups rather than external 10k resistors
                  """
                  
                  
                  import uinput
                  import time
                  import RPi.GPIO as GPIO
                  
                  GPIO.setmode(GPIO.BOARD)
                  # Up, Down, left, right, fire
                  GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP)
                  GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_UP)
                  GPIO.setup(15, GPIO.IN, pull_up_down=GPIO.PUD_UP)
                  GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP)
                  GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_UP)
                  
                  events = (uinput.BTN_JOYSTICK, uinput.ABS_X + (0, 255, 0, 0), uinput.ABS_Y + (0, 255, 0, 0))
                  
                  device = uinput.Device(events)
                  
                  # Bools to keep track of movement
                  fire = False
                  up = False
                  down = False
                  left = False
                  right = False
                  
                  # Center joystick
                  # syn=False to emit an "atomic" (128, 128) event.
                  device.emit(uinput.ABS_X, 128, syn=False)
                  device.emit(uinput.ABS_Y, 128)
                  
                  while True:
                    if (not fire) and (not GPIO.input(7)):  # Fire button pressed
                      fire = True
                      device.emit(uinput.BTN_JOYSTICK, 1)
                    if fire and GPIO.input(7):              # Fire button released
                      fire = False
                      device.emit(uinput.BTN_JOYSTICK, 0) 
                    if (not up) and (not GPIO.input(11)):   # Up button pressed
                      up = True
                      device.emit(uinput.ABS_Y, 0)          # Zero Y
                    if up and GPIO.input(11):               # Up button released
                      up = False
                      device.emit(uinput.ABS_Y, 128)        # Center Y
                    if (not down) and (not GPIO.input(13)): # Down button pressed
                      down = True
                      device.emit(uinput.ABS_Y, 255)        # Max Y
                    if down and GPIO.input(13):             # Down button released
                      down = False
                      device.emit(uinput.ABS_Y, 128)        # Center Y
                    if (not left) and (not GPIO.input(15)): # Left button pressed
                      left = True
                      device.emit(uinput.ABS_X, 0)          # Zero X
                    if left and GPIO.input(15):             # Left button released
                      left = False
                      device.emit(uinput.ABS_X, 128)        # Center X
                    if (not right) and (not GPIO.input(16)):# Right button pressed
                      right = True
                      device.emit(uinput.ABS_X, 255)        # Max X
                    if right and GPIO.input(16):            # Right button released
                      right = False
                      device.emit(uinput.ABS_X, 128)        # Center X
                    time.sleep(.02)  # Poll every 20ms (otherwise CPU load gets too high)
                  

                  https://www.othermod.com

                  1 Reply Last reply Reply Quote 0
                  • S
                    Shojiro
                    last edited by

                    Sorry for necroposting a little, but I was wondering if @adamspc had ever actually managed to get an analog joystick to work, since it has been several months and I haven't seen anything else posted about this.

                    adamspcA 1 Reply Last reply Reply Quote 0
                    • adamspcA
                      adamspc @Shojiro
                      last edited by

                      @Shojiro No progress yet, but that's only because all my time is taken working on the boards I'm designing. I ended up doing a simple joystick using an LM339, but that's only a temporary solution.

                      I will succeed in getting the analog working using the MCP3002, but it won't be soon. Hopefully one of the software guys reading this has time to help out.

                      https://www.othermod.com

                      1 Reply Last reply Reply Quote 0
                      • T
                        Ture
                        last edited by

                        @adamspc I know this thread is old, but I'm currently having the same issue. Did you manage to made any progress with the analog joystick?

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post

                        Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.

                        Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.