genuinequality

Download free music MP3s on genuine quality, the world’s largest online music catalogue, powered by your scrobbles. Free listening, videos, photos, The world’s largest online music catalogue, powered by your scrobbles. Free listening, videos, photos, stats, charts, biographies and concerts. stats, charts, biographies and concerts.

Monday, June 16, 2025

Atari 2600 Controller Shield PCB Revisited

As previously mentioned in my Atari 2600 Controller Shield PCB Build Guide the PCB doesn't work so well with paddle controllers due to the way they are wired up. This is an update to the PCB to allow the paddles to be used in a very similar way to t…
Read on blog or Reader
Site logo image Simple DIY Electronic Music Projects Read on blog or Reader

Atari 2600 Controller Shield PCB Revisited

By Kevin on June 16, 2025

As previously mentioned in my Atari 2600 Controller Shield PCB Build Guide the PCB doesn't work so well with paddle controllers due to the way they are wired up.

This is an update to the PCB to allow the paddles to be used in a very similar way to the original Atari 2600.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to Arduino, see the Getting Started pages.

PCB Update

This is basically the PCB design as described here: Atari 2600 Controller Shield PCB Design but with the addition of a resistor and capacitor in the paddle circuit as shown below.

These are the values used in the original Atari circuit as can be found in the following references:

  • Atari 2600 main circuit: https://atariage.com/2600/archives/schematics/Schematic_2600_Low.html
  • Atari 2600 paddle circuit: https://atariage.com/2600/archives/schematics/Schematic_2600_Accessories_Low.html
  • Details of programming for paddles: "Stella Programmer's Guide" section 12.1, TIA section 8B, Figure 8.

These also describe the operation of the TIA and paddle INPUT circuit:

The block diagram for the TIA shows the transistors mentioned, that are controlled by D7 in VBLANK.

The basic idea being described is that setting D7 turns on the transistors that will drop the voltage from the capacitor to zero. Then the capacitor will charge again and the time it takes to charge depends on the position of the paddle, which is connected to a 1M variable resistor. By measuring the time it takes to charge the capacitor back up, the position of the paddle can be determined.

From all this, we can conclude that the required approach for an Arduino should be as follows (assuming the paddles are connected to analog INPUT ports):

SET pin to OUTPUT
SET pin to LOW
SET pin to INPUT
Start timer
WAIT WHILE (voltage on the analog INPUT pin is NOT HIGH)
Stop timer

This works because the ATmega328P's analog input ports (at least A0 to A5) can also be used as digital input and output ports.

Note: the Arduino reference documentation states that if swapping from digital output to analog input, then the mode should be explicitly set prior to any calls to analogRead (see "caveats" here).

Build Steps

Solder the components in the following order:

  • Resistors
  • Capacitors
  • Arduino headers
  • 9-way D-type connectors

Testing

I recommend performing the general tests described here: PCBs.

The following sketch will read the value of one of the paddle controllers, implementing the algorithm described above.

#define PAD_PIN A0

#define RAW_MAX 950
#define RAW_SHIFT 7
#define RAW_OFFSET 3
#define RAW_BREAK 150000

unsigned long atariRawAnalogRead (int pin) {
unsigned long start = micros();
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
pinMode(pin, INPUT);
while ((analogRead(pin)<RAW_MAX) && (micros()<(start+RAW_BREAK)))
{}
return (micros() - start);
}

int atariAnalogRead (int pin) {
unsigned long val = atariRawAnalogRead(pin) >> RAW_SHIFT;
if (val < RAW_OFFSET) {
return 1023;
} else if (val < 1023+RAW_OFFSET) {
return 1023-(val-RAW_OFFSET);
} else {
return 0;
}
}

void setup() {
Serial.begin(9600);
}

void loop() {
Serial.print(atariRawAnalogRead(PAD_PIN));
Serial.print("\t");
Serial.print(atariAnalogRead(PAD_PIN));
Serial.print("\t");
Serial.println(analogRead(PAD_PIN));
}

The configuration values at the top are determined through a bit of trial-and-error, noting the following:

  • A single reading could take up to 150 mS.
  • The maximum analog reading corresponds to a voltage of around 4.6V, which is around 940 out of 1023.
  • Timing the charging using microseconds gives more resolution, especially at the quicker end.
  • Shifting the measurement >>7 turns the up to 150,000 value into a value of up to 1170.
  • The residual readings are largely in the range 3 to 1170 now, so a subtraction is required to drop that down to 0, and the top reading needs capping at 1023 to match that returned by analogRead().
  • Reversing the sense of the readings means that clockwise reads higher than anticlockwise.
  • Note: if not controller is plugged in, then the while loop would never complete, so a breakout timer value is provided set to the expected maximum of around 150mS.

The Arduino functions are relatively slow compared to direct register access, but as the time out involved is up to 150mS, I'm not too worried about trying to speed up the Arduino calls.

If I was attempting to read all four paddle controllers at the same time, some optimisation would be required. It might even be worth attempting to read them using a timer interrupt and a sampling routine.

If this was to be used properly, some averaging of values would also be required.

Other PCB Notes

  • This PCB still works fine with keypad controllers. The additional resistor and capacitor does not affect the keypad scanning function.
  • This PCB also still works fine with joysticks, as the digital lines have not be altered.
  • It is possible to use this PCB with the "additional resistor" method described in Atari 2600 Controller Shield PCB Build Guide. This requires installing a resistor where the capacitor is meant to go and shorting the existing resistor link together.

Find the updated PCB on GitHub here.

Closing Thoughts

There are now several approaches that can be used to read Atari paddle controllers from an Arduino.

  • Doctor the wiring of the paddles themselves to internally connect the potentiometer to the 5V and GND line, then connect it directly to an Arduino analog input like any other potentiometer.
  • Use the approach described in Atari 2600 Controller Shield PCB Build Guide to add a resistor and make a variable potential divider, adjusting the read values in software.
  • Use the approach described above to time the charging of a capacitor, mirroring how the original Atari circuit and TIA would have worked.

Kevin

Comment
Like
You can also reply to this email to leave a comment.

Simple DIY Electronic Music Projects © 2025.
Unsubscribe or manage your email subscriptions.

WordPress.com and Jetpack Logos

Get the Jetpack app

Subscribe, bookmark, and get real‑time notifications - all from one app!

Download Jetpack on Google Play Download Jetpack from the App Store
WordPress.com Logo and Wordmark title=

Automattic, Inc.
60 29th St. #343, San Francisco, CA 94110

Posted by BigPalaceNews at 1:40 PM
Email ThisBlogThis!Share to XShare to FacebookShare to Pinterest

No comments:

Post a Comment

Newer Post Older Post Home
Subscribe to: Post Comments (Atom)

Search This Blog

About Me

BigPalaceNews
View my complete profile

Blog Archive

  • June (62)
  • May (105)
  • April (95)
  • March (131)
  • February (111)
  • January (104)
  • December (98)
  • November (87)
  • October (126)
  • September (104)
  • August (97)
  • July (112)
  • June (113)
  • May (132)
  • April (162)
  • March (150)
  • February (342)
  • January (232)
  • December (260)
  • November (149)
  • October (179)
  • September (371)
  • August (379)
  • July (360)
  • June (385)
  • May (391)
  • April (395)
  • March (419)
  • February (356)
  • January (437)
  • December (438)
  • November (400)
  • October (472)
  • September (460)
  • August (461)
  • July (469)
  • June (451)
  • May (464)
  • April (506)
  • March (483)
  • February (420)
  • January (258)
  • December (197)
  • November (145)
  • October (117)
  • September (150)
  • August (132)
  • July (133)
  • June (117)
  • May (190)
  • January (48)
Powered by Blogger.