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.
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)