User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Atari 2600 Pi Project

Sat Oct 20, 2012 10:02 pm

Hey there, I got my Raspberry Pi, been fiddling around with it, and now I want to make it into an Atari 2600 emulator using Stella.

So far, I installed Stella, put games onto it, set it up to automatically log in and run Stella after boot up, as shown in this video I made, http://www.youtube.com/watch?v=yQp4RO_eSSo .

Now here's the interesting part! I want to use already existing Atari Joystick and analogue rotary paddles that I own to play these games. I could use a retroUSB board, but since the RPi has GPIOs, I was wondering if there's a means to attach my joysticks to the GPIOs and call back keyboard signals.

Something on the lines of this...

pins 0+1 = Key_up (p1 up)
... 0+2 = Key_down (p1 down)
... 0+3 = Key_left (p1 left)
... 0+4 = Key_right (p1 right)
... 0+5 = Key_Space (p1 fire button)
... 0+6 = Key_Y (p2 up)
... 0+7 = Key_H (p2 down)
... 0+8 = Key_G (p2 left)
... 0+9 = Key_J (p2 right)
... 0+10 = Key_F (p2 fire button)
... 0+11 = Key_F1 (Select)
... 0+12 = Key_F2 (Reset)

Now upon reading this, it looks as if there's more than one ground, and it's not a simple case as just using the pins in the order I picked, http://www.raspberrypi-spy.co.uk/wp-con ... sion-2.png , so I might have to rethink this...

Plus I would LOVE.... to use paddle controls on this emulator to play warlords, Kaboom and Breakout. Is there a way to send resistance to generate a number to move a mouse cursor? Plus how could I sent this up to have 4 paddles at the same time?

User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Re: Atari Pi Project

Sat Oct 20, 2012 10:41 pm

Ah ha...

I came across this...

http://blog.thestateofme.com/2012/08/10 ... -joystick/

Looks like someone made a joystick driver with python.

Now if only I can find a way to get the paddles to work too...?

User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Re: Atari Pi Project

Sun Oct 21, 2012 12:59 am

Ok, I found this great GPIO to key driver written by Chris Swan https://github.com/cpswan/Python/blob/m ... io-kbrd.py and I pretty much changed to so that it supports 2 joysticks, and the console switches such as select and reset.

Once I get stuff to build up a board, and some 9 pin dsubs, I can see if this works! The only issue is that Chris Swan tried this with a MAME emulator and it didn't work because the emulator ignored the uinput signals. Hopefully Stella doesn't ignore it!

Code: Select all

""" rpi-gpio-atari2key.py by Ian Guebert 21 Oct 2012
Atari Joystick to GPIO to Keyboard driver for raspberry Pi, based on Chris Swan's rpi-gpio-kbrd.py driver.
Going to experiment with this to see if 2 Atari joysticks can be used at the same time for Stella Emulator.
Console switches such as Select and Reset have been added, a pause button too for gameplay sake.
"""

""" rpi-gpio-kbrd.py by Chris Swan 9 Aug 2012
GPIO Keyboard driver for Raspberry Pi for use with 80s 5 switch joysticks
*** This did not work with AdvMAME - failed attempt - may be useful for another project
based on python-uinput/examples/keyboard.py by tuomasjjrasanen
https://github.com/tuomasjjrasanen/python-uinput/blob/master/examples/keyboard.py
requires uinput kernel module (sudo modprobe uinput)
requires python-uinput (git clone https://github.com/tuomasjjrasanen/python-uinput)
requires (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/
"""

import uinput
import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
GPIO.setup(3, GPIO.IN)
GPIO.setup(5, GPIO.IN)
GPIO.setup(7, GPIO.IN)
GPIO.setup(8, GPIO.IN)
GPIO.setup(10, GPIO.IN)
GPIO.setup(11, GPIO.IN)
GPIO.setup(12, GPIO.IN)
GPIO.setup(13, GPIO.IN)
GPIO.setup(15, GPIO.IN)
GPIO.setup(16, GPIO.IN)
GPIO.setup(18, GPIO.IN)
GPIO.setup(19, GPIO.IN)
GPIO.setup(21, GPIO.IN)

events = (uinput.KEY_UP, uinput.KEY_DOWN, uinput.KEY_LEFT, uinput.KEY_RIGHT, uinput.KEY_SPACE, uinput.KEY_Y, uinput.KEY_H, uinput.KEY_G, uinput.KEY_J, uinput.KEY_F, uinput.KEY_F1, uinput.KEY_F2, uinput.KEY_PAUSE)

device = uinput.Device(events)

1fire = False
1up = False
1down = False
1left = False
1right = False
2fire = False
2up = False
2down = False
2left = False
2right = False
select = False
resetB = False
pause = False



while True:

#Player 1 controls

  if (not 1fire) and (not GPIO.input(10)):  # player 1 Fire button pressed
    1fire = True
    device.emit(uinput.KEY_SPACE, 1) # player 1 Press space bar

  if 1fire and GPIO.input(10):  # player 1 Fire button released
    1fire = False
    device.emit(uinput.KEY_SPACE, 0) # player 1 Release space bar

  if (not 1up) and (not GPIO.input(3)):  # player 1 Up button pressed
    1up = True
    device.emit(uinput.KEY_UP, 1) # player 1 Press Up key

  if 1up and GPIO.input(3):  # player 1 Up button released
    1up = False
    device.emit(uinput.KEY_UP, 0) # player 1 Release Up key

  if (not 1down) and (not GPIO.input(5)):  # player 1 Down button pressed
    1down = True
    device.emit(uinput.KEY_DOWN, 1) # player 1 Press Down key

  if 1down and GPIO.input(5):  # player 1 Down button released
    1down = False
    device.emit(uinput.KEY_DOWN, 0) # player 1 Release Down key

  if (not 1left) and (not GPIO.input(7)):  # player 1 Left button pressed
    1left = True
    device.emit(uinput.KEY_LEFT, 1) # player 1 Press Left key

  if 1left and GPIO.input(7):  # player 1 Left button released
    1left = False
    device.emit(uinput.KEY_LEFT, 0) # player 1 Release Left key

  if (not 1right) and (not GPIO.input(8)):  # player 1 Right button pressed
    1right = True
    device.emit(uinput.KEY_RIGHT, 1) # player 1 Press Right key

  if 1right and GPIO.input(8):  # player 1 Right button released
    1right = False
    device.emit(uinput.KEY_RIGHT, 0) # player 1 Release Right key

#Player 2 controls

  if (not 2fire) and (not GPIO.input(18)):  # player 2 Fire button pressed
    2fire = True
    device.emit(uinput.KEY_F, 1) # player 2 Press F Key

  if 2fire and GPIO.input(18):  # player 2 Fire button released
    2fire = False
    device.emit(uinput.KEY_F, 0) # player 2 Release F Key

  if (not 2up) and (not GPIO.input(11)):  # player 2 Up button pressed
    2up = True
    device.emit(uinput.KEY_Y, 1) # player 2 Press Y Key

  if 2up and GPIO.input(11):  # player 2 Up button released
    2up = False
    device.emit(uinput.KEY_Y, 0) # player 2 Release Y key

  if (not 2down) and (not GPIO.input(13)):  # player 2 Down button pressed
    2down = True
    device.emit(uinput.KEY_H, 1) # player 2 Press H key

  if 2down and GPIO.input(13):  # player 2 Down button released
    2down = False
    device.emit(uinput.KEY_H, 0) # player 2 Release H key

  if (not 2left) and (not GPIO.input(15)):  # player 2 Left button pressed
    2left = True
    device.emit(uinput.KEY_G, 1) # player 2 Press G key

  if 2left and GPIO.input(15):  # player 2 Left button released
    2left = False
    device.emit(uinput.KEY_G, 0) # player 2 Release G key

  if (not 2right) and (not GPIO.input(16)):  # player 2 Right button pressed
    2right = True
    device.emit(uinput.KEY_J, 1) # player 2 Press J key

  if 2right and GPIO.input(16):  # player 2 Right button released
    2right = False
    device.emit(uinput.KEY_J, 0) # player 2 Release J key

#Switches

  if (not select) and (not GPIO.input(19)): # Select button pressed
	select = True
	device.emit(uinput.KEY_F1, 1) # F1 key pressed

  if select and GPIO.input(19): # release select button
	select = False
	device.emit(uinput.KEY_F1, 0) # release F1 key

  if (not resetB) and (not GPIO.input(21)): # Reset button pressed
	resetB = True
	device.emit(uinput.KEY_F2, 1) # F2 key pressed

  if resetB and GPIO.input(21): # release reset button
	resetB = False
	device.emit(uinput.KEY_F2, 0) # release F2 key

  if (not pause) and (not GPIO.input(12)):
	pause = True
	device.emit(uinput.KEY_PAUSE, 1)

  if pause and GPIO.input(12):
	pause = False
	device.emit(uinput.KEY_PAUSE, 0)

  time.sleep(.04)
Does this code look right to you guys?

teeth_03
Posts: 284
Joined: Sat Sep 08, 2012 12:02 am

Re: Atari Pi Project

Sun Oct 21, 2012 5:09 pm

Have you been able to get 2 player to work? I have emulationstation/retropie and it doesnt.

Also, i wonder if the usb to dual joystick adapter works fine with the Pi...

User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Re: Atari Pi Project

Sun Oct 21, 2012 6:36 pm

teeth_03 wrote:Have you been able to get 2 player to work? I have emulationstation/retropie and it doesnt.

Also, i wonder if the usb to dual joystick adapter works fine with the Pi...
Well the whole point of this is so that I don't need to use a USB controller, or a RetroUSB adapter. The Atari 2600 joystick is just a set of switches, no other electronics, so I should be able to program a driver that will read when a GPIO is turned on and off and emulate a keyboard stroke from it.

When I get the 2 player support done, I want to work on paddle controller support.

teeth_03
Posts: 284
Joined: Sat Sep 08, 2012 12:02 am

Re: Atari Pi Project

Sun Oct 21, 2012 10:44 pm

I noticed you can buy new manufactured joysticks, but not the paddles which is a shame.

So are you planning on producing a gpio to atari adapter i take it?

User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Re: Atari Pi Project

Sun Oct 21, 2012 10:53 pm

teeth_03 wrote:So are you planning on producing a gpio to atari adapter i take it?
Not an adapter per say... It's just a wiring job with pull-up resistors.

I'll post up a wiring diagram in a moment...

User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Re: Atari Pi Project

Sun Oct 21, 2012 11:23 pm

Here we go, this is wiring I've done including the pull up resistors...

Image

User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Re: Atari Pi Project

Sun Oct 21, 2012 11:55 pm

And a 2 player version of the same wiring...

Image

Thing is, I'm going to test the single player wiring set up before doing the 2 player. Then I can work on the paddle support after that.

precious_pony
Posts: 34
Joined: Tue May 22, 2012 11:09 pm

Re: Atari Pi Project

Mon Oct 22, 2012 2:03 pm

Great thread.

User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Re: Atari Pi Project

Mon Oct 22, 2012 4:01 pm

Ok, I did a bit of a wiring job using a breadboard, motherboard header extension cables, a 9 pin dsub, some resistors and wires. And the result is this!

Image

All I need to do now is compile that driver I built... however I keep getting this!

Code: Select all

[email protected] ~/GPIOtoKEY $ python -c rpi-gpio-atari2key.py
Traceback (most recent call last):
  File "<string>", line 1, in <module>
NameError: name 'rpi' is not defined
[email protected] ~/GPIOtoKEY $
Now... I have installed raspberry-gpio-python from "hg clone https://code.google.com/p/raspberry-gpio-python/" but it's still not compiling! Is there something that I'm missing and/or is there something wrong with the code?

User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Re: Atari Pi Project

Tue Oct 23, 2012 10:10 pm

OK, I solved the whole rpi thing, there were a few things I needed to install such as the GPIO drivers. However I'm having a hard time trying to install the uinput command...

[email protected] ~/GPIOtoKEY $ sudo apt-get install python-uinput
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package python-uinput
[email protected] ~/GPIOtoKEY $

Thing is, why is it not locating uinput? why can't I download this!?

User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Re: Atari Pi Project

Tue Oct 23, 2012 11:21 pm

After many installations and tweaking, I got something working!

http://www.youtube.com/watch?v=fUv6VUfXisY

But as you might see on the video, I have to run Stella and my atari-to-gpio program in separate terminals. It would be nice to run my atari-to-gpio.py as a background process rather than a program that overrides a ternminal.

Any ideas on how to do this?

User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Re: Atari Pi Project

Wed Oct 24, 2012 1:27 am

Ok, I figured it out, by using "<command> &" I can run my atari to gpio program in the background. Plus I discovered that after each boot you need to run the "sudo modprobe uinput" command before the atari to gpio program can work.

So... here's how I set up my .profile file.

sudo modprobe uinput
sudo python ~/GPIOtoKEY/AtariToKey.py install &
stella

Now I need to make my player two port and figure out what to do with the paddles!

marqs
Posts: 207
Joined: Sat Jun 09, 2012 11:34 am

Re: Atari Pi Project

Wed Oct 24, 2012 9:40 pm

Good work!

Have you tried using 3.3V and internal pull-ups? I think atari vcs joysticks are purely switch based (besides the pot), so they should work well that setup too.

The paddle could propably be read with a suitable resistor network, although it'd require quite many pins for good A/D.

There's also a db9 joystick driver for parport in the kernel, which could be modified to work with GPIOs with a bit effort. I did similar port for the gamecon driver, and the most time-taking task actually was to generate the kernel headers package for build environment preparation.

db9.c is in located drivers/input/joystick in the kernel tree, and is documented in Documentation/input/joystick-parport.txt

User avatar
SepticLemon
Posts: 32
Joined: Sun Oct 07, 2012 3:52 pm

Re: Atari Pi Project

Wed Oct 24, 2012 10:54 pm

marqs wrote:Have you tried using 3.3V and internal pull-ups? I think atari vcs joysticks are purely switch based (besides the pot), so they should work well that setup too.
Could do... But I'm sticking with 5v since the paddle's potentiometer uses a 5v input. You know, one less thing to worry about. However... I've been studying ADCs today, and it looks like I'm going to use 3.3v for a MCP3008, which I'm going to use to to convert resistance into a digital number then use that to plot the position for a paddles axis.
marqs wrote:The paddle could probably be read with a suitable resistor network, although it'd require quite many pins for good A/D.
Heh, I'm a bit of a noob when it comes to electronics, so I had to look up what a resistor network is. And hey, that would seriously help and make room for when I build the final PCB for this Atari-to-GPIO interface.
marqs wrote:There's also a db9 joystick driver for parport in the kernel, which could be modified to work with GPIOs with a bit effort. I did similar port for the gamecon driver, and the most time-taking task actually was to generate the kernel headers package for build environment preparation.

db9.c is in located drivers/input/joystick in the kernel tree, and is documented in Documentation/input/joystick-parport.txt
Ok, interesting... Just because I noticed when I was making a mock script for the upcoming paddle-to-gpio python program, I was using this tutorial about using the MCP3008 on the RPi's GPIOs and noticed that pin 10 goes to pin 25, which from this image looks like it ends up on a ground. Though I have noticed that the names of each GPIO pin isn't the same as the pin number, e.g. pin 19 is GPIO10 according to that image. This might get confusing, lmao!

Anyway, as a progress report, I got more motherboard header extensions from work and built up a player 2 port on my breadboard...

Image

Image

And here are the results!


EDIT:- Oh yeah, if anyone want to see, this is the paddle-to-gpio python script I bodged up whilst reading this tutorial...

Code: Select all

import uinput
import time
import os
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
DEBUG = 1

def readadc(adcnum, clockpin, mosipin, misopin, cspin):
        if ((adcnum > 7) or (adcnum < 0)):
                return -1
        GPIO.output(cspin, True)

        GPIO.output(clockpin, False)  # start clock low
        GPIO.output(cspin, False)     # bring CS low

        commandout = adcnum
        commandout |= 0x18  # start bit + single-ended bit
        commandout <<= 3    # we only need to send 5 bits here
        for i in range(5):
                if (commandout & 0x80):
                        GPIO.output(mosipin, True)
                else:
                        GPIO.output(mosipin, False)
                commandout <<= 1
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)

        adcout = 0
        # read in one empty bit, one null bit and 10 ADC bits
        for i in range(12):
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)
                adcout <<= 1
                if (GPIO.input(misopin)):
                        adcout |= 0x1

        GPIO.output(cspin, True)
        
        adcout >>= 1       # first bit is 'null' so drop it
        return adcout

SPICLK = 19
SPIMISO = 21
SPIMOSI = 23
SPICS = 25

GPIO.setup(SPIMOSI, GPIO.OUT)
GPIO.setup(SPIMISO, GPIO.IN)
GPIO.setup(SPICLK, GPIO.OUT)
GPIO.setup(SPICS, GPIO.OUT)

events = (uinput.ABS_X + (0, 255, 0, 0), uinput.ABS_Y + (0, 255, 0, 0))
device = uinput.Device(events)


# 10k trim pot connected to adc #0
paddle_ADC0 = 0;
paddle_ADC1 = 1;

last_read = 0       # this keeps track of the last potentiometer value
tolerance = 5       # to keep from being jittery we'll only change
                    # volume when the pot has moved more than 5 'counts'

while True:
	#Start reading Paddle 0 (player 1)

        
        trim_pot0_changed = False			# we'll assume that paddle 0 didn't move

        trim_pot0 = readadc(paddle_ADC0, SPICLK, SPIMOSI, SPIMISO, SPICS)	# read Paddle 0
        
        pot0_adjust = abs(trim_pot0 - last_read)	# how much has it changed since the last read?

        if ( pot0_adjust > tolerance ):
               trim_pot0_changed = True

        if ( trim_pot0_changed ):
                set_xAxis = trim_pot0 / 4		# convert 10bit adc0 (0-1024) trim pot read 0-256 for joystick 1 X axis
                set_xAxis = round(set_xAxis)      	# round out decimal value
                set_xAxis = int(set_xAxis)        	# cast axis as integer

		device.emit(uinput.ABS_X, set_xAxis)	#Set joystick x axis to the rounded down value given from paddle 0

        last_read = trim_pot0				# save the potentiometer reading for the next loop





	#Start reading Paddle 1 (player 2)

        trim_pot1_changed = False			# we'll assume that the paddle 1 didn't move

        trim_pot1 = readadc(paddle_ADC1, SPICLK, SPIMOSI, SPIMISO, SPICS)	# Read paddle 1

        pot1_adjust = abs(trim_pot1 - last_read)	# how much has it changed since the last read?

        if ( pot1_adjust > tolerance ):
               trim_pot0_changed = True

        if ( trim_pot_changed ):
                set_yAxis = trim_pot1 / 4		# convert 10bit adc0 (0-1024) trim pot read 0-256 for joystick 1 X axis
                set_yAxis = round(set_yAxis)      	# round out decimal value
                set_yAxis = int(set_yAxis)        	# cast axis as integer

		device.emit(uinput.ABS_Y, set_yAxis)	#Set joystick y axis to the rounded down value given from paddle 1

        # save the potentiometer reading for the next loop
        last_read = trim_pot1



        time.sleep(.02)

User avatar
Craggus2000
Posts: 5
Joined: Wed Jan 15, 2014 8:25 pm

Re: Atari Pi Project

Wed Jan 15, 2014 8:27 pm

Hi, did you get paddles working reliably too?
Don't suppose you could post a new circuit diagram with them included and any code required?
Thanks!
Craggus2000
"If it ain't broke, break it and make it better"

User avatar
Richard-TX
Posts: 1549
Joined: Tue May 28, 2013 3:24 pm
Location: North Texas

Re: Atari Pi Project

Wed Jan 15, 2014 9:29 pm

A simple ADC on the I2C or SPI bus will be able to handle the paddles.

Here is a fellow that made a similar controller for the Rpi and a PCF8591

http://wiki.rocrail.net/doku.php?id=gca-pi04-en

Here is a cheap 4 channel ADC also based on the PCF8591

http://www.ebay.com/itm/1PC-New-AD-DA-C ... 2c71d20f9d
Richard
Doing Unix since 1985.
The 9-25-2013 image of Wheezy can be found at:
http://downloads.raspberrypi.org/raspbian/images/raspbian-2013-09-27/2013-09-25-wheezy-raspbian.zip

ChinMuzik
Posts: 6
Joined: Thu Dec 03, 2015 9:49 am

Re: Atari Pi Project

Thu Dec 03, 2015 9:59 am

Has anybody succesfully implemented the ADC? (Or, have gotten the paddles to work?)

I'm looking to build a wireless BT paddle for Stella based off the Bluefruit E-Key HID board.

User avatar
karrika
Posts: 1045
Joined: Mon Oct 19, 2015 6:21 am
Location: Finland

Re: Atari Pi Project

Thu Dec 03, 2015 10:44 am

You could also use digital rotary knobs for paddles.
https://www.sparkfun.com/datasheets/Com ... 700198.pdf
They take 2 GPIO inputs and you get a pattern when rotating it

00
10
11
01
00

Then it is just a little code to find out which way you are rotating.

ChinMuzik
Posts: 6
Joined: Thu Dec 03, 2015 9:49 am

Re: Atari Pi Project

Fri Dec 04, 2015 4:07 am

Coding was something I kind of wanted to stay away from. Even with wiring schematics im fairly ignorant (this would be my first project ever).

Is it as simple as installing the ADC on the board in the proper contacts? I was under the assumption it'd be easy because Stella supports analog input.

User avatar
Craggus2000
Posts: 5
Joined: Wed Jan 15, 2014 8:25 pm

Re: Atari Pi Project

Fri Dec 08, 2017 11:40 am

Sorry to drag up an old post, but does anyone know if or similar this exists for the raspberry pi 3?
Thanks.
Craggus2000
"If it ain't broke, break it and make it better"

pitari
Posts: 2
Joined: Tue Jul 03, 2018 2:41 pm

Re: Atari Pi Project

Wed Jul 04, 2018 11:22 am

Hi
Im not sure if your after a solution to the analogue joystick problems or a working Atari VCS emulator for the Raspberry PI 3 but if its the latter there is this www.pitarivcs.co.uk which has 2 player support with USB controllers and should work on the PI 3. However, If you are using the PI 3 I think you may have to disable the bluetooth to free up the UART.

Devalis
Posts: 1
Joined: Sun Sep 16, 2018 3:25 am

Re: Atari 2600 Pi Project

Sun Sep 16, 2018 3:26 am

I too am working on a project like this, but I'm using a Pi Zero. Has anyone had any success connecting the paddle controller to the GPIO?

Return to “Gaming”

Who is online

Users browsing this forum: No registered users and 9 guests