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:
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
No comments:
Post a Comment