Analog joystick installation questions

Here is all the tutorials, FAQ and support for RetroStone
Post Reply
Brandon
Posts: 21
Joined: Sun 19 Aug 2018 15:49

Analog joystick installation questions

Post by Brandon » Fri 14 Sep 2018 22:31

Hi all,

I didn't see this posted so here goes...

I'd like to add an analog joystick. (I have one lying around).

The 8Bcraft site has a tutorial to mod the Retrostone but it says:
"IMPORTANT : Joystick driver is not yet functional!"

Also it says the parts needed are:
Analog joystick
MCP3208 SMD SOIC package

But the tutorial only mentions how to install the joystick, no mention of installing the MCP3208.
It also says "The buttons and joystick should work out of the box"

Could someone clear up how this should be done?

Thanks

Brandon
Posts: 21
Joined: Sun 19 Aug 2018 15:49

Re: Analog joystick installation questions

Post by Brandon » Sat 15 Sep 2018 07:50

Ok I see it now. It is hard to see, but there is an area on the PCB for the MCP3208.

But once installed, will the joystick work or are drivers required?

User avatar
Admin
Administrateur du site
Posts: 296
Joined: Sat 10 Dec 2016 13:12

Re: Analog joystick installation questions

Post by Admin » Mon 17 Sep 2018 10:24

Yes check the :
Step 8 : Solder the MCP3208, if you have hot air solder station you can use it, or just use regular (small) solder iron. Check on youtube how to solder chips if you don’t know how. Don’t solder it reversed side ! The writing on the chips should be the same side as the writing on the PCB.
About the joystick driver I had not much time recently to work on it. I started to work on it but it was not working yet and I had no further time to work on it since.

The source I used is this : http://codelectron.com/how-to-setup-2-a ... e-pi-zero/

Below is the GPIO driver (drivername.py) including the joystick that I wrote. It seemed correct to me but it did not worked on my first attempt. But it could just have been something that I did not soldered correctly or just a typo in the script...

Note this driver is used for GPIO buttons with pyA20 package. Driver should be able to use same pyA20 package. BTW it should be possible to use pyA20 SPI package instead of spidev. I used spidev because it's what they used on codelectron webpage.

If you want to test this driver you will have to replace current driver python file with this one. I am not sure exactly how it's done since retrorangepi devs enabled by default the retrostone GPIO driver. (vs the other versions of retrorangepi where you have to enable it from retropie emulator/retrorangepi/GPIO)

Code: Select all

#!/usr/bin/env python

import spidev
import evdev
import uinput
from time import sleep
from evdev import InputDevice, KeyEvent, UInput, AbsInfo, ecodes as e
from pyA20.gpio import gpio
from pyA20.gpio import port
from pyA20.gpio import connector

class MCP3208:
        def __init__(self, spi_channel=0):
                self.spi_channel = spi_channel
                self.conn = spidev.SpiDev(1, spi_channel)
                self.conn.max_speed_hz = 1000000 # 1MHz
 
        def __del__( self ):
                self.close
 
        def close(self):
                if self.conn != None:
                        self.conn.close
                        self.conn = None
 
        def bitstring(self, n):
                s = bin(n)[2:]
                return '0'*(8-len(s)) + s
 
    def ReadInput(self,Sensor):
        adc = self.conn.xfer2([1,(8+Sensor)<<4,0])
        data = ((adc[1]&3) << 8) + adc[2]
        return data
 
        def read(self, adc_channel=0):
                # build command
                cmd  = 128 # start bit
                cmd +=  64 # single end / diff
                if adc_channel % 2 == 1:
                        cmd += 8
                if (adc_channel/2) % 2 == 1:
                        cmd += 16
                if (adc_channel/4) % 2 == 1:
                        cmd += 32
 
                # send & receive data
                reply_bytes = self.conn.xfer2([cmd, 0, 0, 0])
 
                #
                reply_bitstring = ''.join(self.bitstring(n) for n in reply_bytes)
#                print reply_bitstring
 
                # see also... http://akizukidenshi.com/download/MCP3204.pdf (page.20)
                reply = reply_bitstring[5:17]
                return int(reply, 2)

events = ([
		uinput.BTN_A,
		uinput.BTN_B,
		uinput.BTN_C,
		uinput.BTN_X,
		uinput.BTN_Y,
		uinput.BTN_Z,
		uinput.BTN_TL,
		uinput.BTN_TR,
		uinput.BTN_THUMBL,
		uinput.BTN_THUMBR,
		uinput.BTN_SELECT,
		uinput.BTN_START,
		uinput.BTN_TL2,
		uinput.BTN_TR2,
		uinput.ABS_X + (0,255,0,0),
		uinput.ABS_Y + (0,255,0,0),
		uinput.BTN_DPAD_UP,
		uinput.BTN_DPAD_DOWN,
		uinput.BTN_DPAD_LEFT,
		uinput.BTN_DPAD_RIGHT,
	])
#could use BTN_DPAD_UP BTN_DPAD_DOWN BTN_DPAD_LEFT BTN_DPAD_RIGHT but is it better?

gamepad = uinput.Device(events,"RetroStone Controle",0x00)

gamepad.emit(uinput.ABS_X, 128, syn=False)
gamepad.emit(uinput.ABS_Y, 128)

#--------------- define botoes -----------------
	# ---- PLAYER 1 ---------#
bt_up_p1 = port.PD12
bt_down_p1 = port.PD5
bt_left_p1 = port.PD0
bt_right_p1 = port.PD11

bt_l_p1 = port.PD6
bt_x_p1 = port.PD13
bt_y_p1 = port.PD9
bt_r_p1 = port.PD7
bt_b_p1 = port.PD15
bt_a_p1 = port.PD14

bt_select_p1 = port.PD4
bt_start_p1 = port.PD1

bt_left_trigger_p1 = port.PD8
bt_right_trigger_p1 = port.PD3

#optional buttons
bt_c_p1 = port.PC9
bt_z_p1 = port.PE3
bt_d_p1 = port.PA3
bt_e_p1 = port.PA15



#--------------------------------Initialize module. Always called first
spi = MCP3208(0)
gpio.init()

gpio.setcfg(bt_up_p1, gpio.INPUT)
gpio.pullup(bt_up_p1, gpio.PULLUP)

gpio.setcfg(bt_down_p1, gpio.INPUT)
gpio.pullup(bt_down_p1, gpio.PULLUP)

gpio.setcfg(bt_left_p1, gpio.INPUT)
gpio.pullup(bt_left_p1, gpio.PULLUP)

gpio.setcfg(bt_right_p1, gpio.INPUT)
gpio.pullup(bt_right_p1, gpio.PULLUP)


gpio.setcfg(bt_l_p1, gpio.INPUT)
gpio.pullup(bt_l_p1, gpio.PULLUP)

gpio.setcfg(bt_x_p1, gpio.INPUT)
gpio.pullup(bt_x_p1, gpio.PULLUP)

gpio.setcfg(bt_y_p1, gpio.INPUT)
gpio.pullup(bt_y_p1, gpio.PULLUP)

gpio.setcfg(bt_r_p1, gpio.INPUT)
gpio.pullup(bt_r_p1, gpio.PULLUP)

gpio.setcfg(bt_b_p1, gpio.INPUT)
gpio.pullup(bt_b_p1, gpio.PULLUP)

gpio.setcfg(bt_a_p1, gpio.INPUT)
gpio.pullup(bt_a_p1, gpio.PULLUP)

gpio.setcfg(bt_c_p1, gpio.INPUT)
gpio.pullup(bt_c_p1, gpio.PULLUP)

gpio.setcfg(bt_z_p1, gpio.INPUT)
gpio.pullup(bt_z_p1, gpio.PULLUP)

gpio.setcfg(bt_d_p1, gpio.INPUT)
gpio.pullup(bt_d_p1, gpio.PULLUP)

gpio.setcfg(bt_e_p1, gpio.INPUT)
gpio.pullup(bt_e_p1, gpio.PULLUP)

gpio.setcfg(bt_select_p1, gpio.INPUT)
gpio.pullup(bt_select_p1, gpio.PULLUP)

gpio.setcfg(bt_start_p1, gpio.INPUT)
gpio.pullup(bt_start_p1, gpio.PULLUP)

gpio.setcfg(bt_left_trigger_p1, gpio.INPUT)
gpio.pullup(bt_left_trigger_p1, gpio.PULLUP)

gpio.setcfg(bt_right_trigger_p1, gpio.INPUT)
gpio.pullup(bt_right_trigger_p1, gpio.PULLUP)

	
_bt_up_p1 = False
_bt_down_p1 = False
_bt_left_p1 = False
_bt_right_p1 = False
_bt_a_p1 = False
_bt_b_p1 = False
_bt_x_p1 = False
_bt_y_p1 = False
_bt_c_p1 = False
_bt_z_p1 = False
_bt_d_p1 = False
_bt_e_p1 = False
_bt_l_p1 = False
_bt_r_p1 = False
_bt_select_p1 = False
_bt_start_p1 = False
_bt_left_trigger_p1 = False
_bt_right_trigger_p1 = False

joystick_spi_LR = 0
joystick_spi_UD = 0
_joystick_spi_LR = 0
_joystick_spi_UD = 0


while True:
	#------ player 1 -----------#		
#bt a =====================
	if (not _bt_a_p1) and (gpio.input(bt_a_p1) == 0):
		_bt_a_p1 = True
		gamepad.emit(uinput.BTN_A, 1)	
	if (_bt_a_p1) and (gpio.input(bt_a_p1) == 1):
		_bt_a_p1 = False
		gamepad.emit(uinput.BTN_A, 0)	
#bt b =====================

	if (not _bt_b_p1) and (gpio.input(bt_b_p1) == 0):
		_bt_b_p1 = True
		gamepad.emit(uinput.BTN_B, 1)	
	if (_bt_b_p1) and (gpio.input(bt_b_p1) == 1):
		_bt_b_p1 = False
		gamepad.emit(uinput.BTN_B, 0)	

#bt X =====================

	if (not _bt_x_p1) and (gpio.input(bt_x_p1) == 0):
		_bt_x_p1 = True
		gamepad.emit(uinput.BTN_X, 1)	
	if (_bt_x_p1) and (gpio.input(bt_x_p1) == 1):
		_bt_x_p1 = False
		gamepad.emit(uinput.BTN_X, 0)	
#bt Y =====================

	if (not _bt_y_p1) and (gpio.input(bt_y_p1) == 0):
		_bt_y_p1 = True
		gamepad.emit(uinput.BTN_Y, 1)	
	if (_bt_y_p1) and (gpio.input(bt_y_p1) == 1):
		_bt_y_p1 = False
		gamepad.emit(uinput.BTN_Y, 0)	

#bt C =====================

	if (not _bt_c_p1) and (gpio.input(bt_c_p1) == 0):
		_bt_c_p1 = True
		gamepad.emit(uinput.BTN_C, 1)	
	if (_bt_c_p1) and (gpio.input(bt_c_p1) == 1):
		_bt_c_p1 = False
		gamepad.emit(uinput.BTN_C, 0)	
#bt Z =====================

	if (not _bt_z_p1) and (gpio.input(bt_z_p1) == 0):
		_bt_z_p1 = True
		gamepad.emit(uinput.BTN_Z, 1)	
	if (_bt_z_p1) and (gpio.input(bt_z_p1) == 1):
		_bt_z_p1 = False
		gamepad.emit(uinput.BTN_Z, 0)	

#bt D =====================

	if (not _bt_d_p1) and (gpio.input(bt_d_p1) == 0):
		_bt_d_p1 = True
		gamepad.emit(uinput.BTN_THUMBL, 1)	
	if (_bt_d_p1) and (gpio.input(bt_d_p1) == 1):
		_bt_d_p1 = False
		gamepad.emit(uinput.BTN_THUMBL, 0)	
#bt E =====================

	if (not _bt_e_p1) and (gpio.input(bt_e_p1) == 0):
		_bt_e_p1 = True
		gamepad.emit(uinput.BTN_THUMBR, 1)	
	if (_bt_e_p1) and (gpio.input(bt_e_p1) == 1):
		_bt_e_p1 = False
		gamepad.emit(uinput.BTN_THUMBR, 0)	
		
#bt L =====================
	if (not _bt_l_p1) and (gpio.input(bt_l_p1) == 0):
		_bt_l_p1 = True
		gamepad.emit(uinput.BTN_TL, 1)	
	if (_bt_l_p1) and (gpio.input(bt_l_p1) == 1):
		_bt_l_p1 = False
		gamepad.emit(uinput.BTN_TL, 0)	
#bt R =====================
	if (not _bt_r_p1) and (gpio.input(bt_r_p1) == 0):
		_bt_r_p1 = True
		gamepad.emit(uinput.BTN_TR, 1)	
	if (_bt_r_p1) and (gpio.input(bt_r_p1) == 1):
		_bt_r_p1 = False
		gamepad.emit(uinput.BTN_TR, 0)
#bt select =====================
	if (not _bt_select_p1) and (gpio.input(bt_select_p1) == 0):
		_bt_select_p1 = True
		gamepad.emit(uinput.BTN_SELECT, 1)	
	if (_bt_select_p1) and (gpio.input(bt_select_p1) == 1):
		_bt_select_p1 = False
		gamepad.emit(uinput.BTN_SELECT, 0)	
#bt start =====================
	if (not _bt_start_p1) and (gpio.input(bt_start_p1) == 0):
		_bt_start_p1 = True
		gamepad.emit(uinput.BTN_START, 1)	
	if (_bt_start_p1) and (gpio.input(bt_start_p1) == 1):
		_bt_start_p1 = False
		gamepad.emit(uinput.BTN_START, 0)
#bt L2 =====================
	if (not _bt_left_trigger_p1) and (gpio.input(bt_left_trigger_p1) == 0):
		_bt_left_trigger_p1 = True
		gamepad.emit(uinput.BTN_TL2, 1)	
	if (_bt_left_trigger_p1) and (gpio.input(bt_left_trigger_p1) == 1):
		_bt_left_trigger_p1 = False
		gamepad.emit(uinput.BTN_TL2, 0)	
#bt R2 =====================
	if (not _bt_right_trigger_p1) and (gpio.input(bt_right_trigger_p1) == 0):
		_bt_right_trigger_p1 = True
		gamepad.emit(uinput.BTN_TR2, 1)	
	if (_bt_right_trigger_p1) and (gpio.input(bt_right_trigger_p1) == 1):
		_bt_right_trigger_p1 = False
		gamepad.emit(uinput.BTN_TR2, 0)	
####DIRECTIONS P1 ###########################

#bt up =====================
	if (not _bt_up_p1) and (gpio.input(bt_up_p1) == 0):
		_bt_up_p1 = True
		gamepad.emit(uinput.BTN_DPAD_UP, 1)	
	if (_bt_up_p1) and (gpio.input(bt_up_p1) == 1):
		_bt_up_p1 = False
		gamepad.emit(uinput.BTN_DPAD_UP, 0)
#bt down =====================
	if (not _bt_down_p1) and (gpio.input(bt_down_p1) == 0):
		_bt_down_p1 = True
		gamepad.emit(uinput.BTN_DPAD_DOWN, 1)	
	if (_bt_down_p1) and (gpio.input(bt_down_p1) == 1):
		_bt_down_p1 = False
		gamepad.emit(uinput.BTN_DPAD_DOWN, 0)
#bt left =====================
	if (not _bt_left_p1) and (gpio.input(bt_left_p1) == 0):
		_bt_left_p1 = True
		gamepad.emit(uinput.BTN_DPAD_LEFT, 1)	
	if (_bt_left_p1) and (gpio.input(bt_left_p1) == 1):
		_bt_left_p1 = False
		gamepad.emit(uinput.BTN_DPAD_LEFT, 0)
#bt right =====================
	if (not _bt_right_p1) and (gpio.input(bt_right_p1) == 0):
		_bt_right_p1 = True
		gamepad.emit(uinput.BTN_DPAD_RIGHT, 1)	
	if (_bt_right_p1) and (gpio.input(bt_right_p1) == 1):
		_bt_right_p1 = False
		gamepad.emit(uinput.BTN_DPAD_RIGHT, 0)
#joystick =====================	
	joystick_spi_LR = spi.ReadInput(1)/4 #/4 because spi read 12 bits, ie 0 to 1023 and we need in range 0 to 253
	if (_joystick_spi_LR != joystick_spi_LR)
		_joystick_spi_LR = joystick_spi_LR
		gamepad.emit(uinput.ABS_X, joystick_spi_LR)
	
	joystick_spi_UD = spi.ReadInput(2)/4
	if (_joystick_spi_UD != joystick_spi_UD)
		_joystick_spi_UD = joystick_spi_UD
		gamepad.emit(uinput.ABS_X, joystick_spi_UD)
		
		

	
	
	
	
	sleep(.02)	

Beads3
Posts: 13
Joined: Mon 20 Aug 2018 19:36

Re: Analog joystick installation questions

Post by Beads3 » Fri 5 Oct 2018 05:39

@Brandon: Did you ever attempt to get this working?

jutleys
Posts: 21
Joined: Sat 25 Aug 2018 10:51

Re: Analog joystick installation questions

Post by jutleys » Sat 13 Oct 2018 22:59

I want to do a mod but i need something to work on.

Post Reply