I've had floating in the back of my mind wanting to make a modern controller adapter for the Atari 5200. The 5200 controller is an analog joystick, two buttons, and a keypad. There are some modern controller projects that are really cool. As far as I can tell, they use digitally-controlled resistors to actuate the potentiometer inputs on the POKEY chip. Makes sense because that's what they were designed for - reading resistors.
The POKEY, along with a few external components, basically measures the time constant of an RC circuit. The system has an 1800-ohm resistor and 0.047 uF capacitor internal and the controller or paddle has a 0.5-1 M-ohm potentiometer. This makes for time constants ranging from <100 us to >10 ms. The operation is described in
section 4 of the POKEY
datasheet. The RC circuit can be seen in this excerpt of the
5200 schematic. The components on P0 (pin 14) are labeled.
The inputs P0-P7 are fed to Schmidt trigger inverters, which will go from high-to-low when the capacitor voltage reaches about 2 volts. The time that takes is determined by the resistance of the potentiometer. In otherwords, the time it takes to charge up the capacitor is measured by the POKEY.
Another way to charge the capacitor is to send in pulses of current (charge) over some time. I wondered if I could use the pulse width modulation (PWM) feature on modern microcontrollers, like the Atmega 328p used in the Arduino, to control how fast the capacitor charges. I had limited success. It turns out the PWM resolution required is much too fine. I would have to resort to additional timers and interrupts to fiddle with the PWM duty cycle and frequency.
Timers. Time. Hmmm. Charge up the capacitor at the right time!
Inside the POKEY is also a "dump transistor" that discharges the capacitor to reset the circuit for the next frame and reading. This is done by hitting the POTGO line. It can be seen in this schematic, again from the datasheet:
It's easy to charge up the capacitor - just apply some voltage for a few 10's of microseconds. But how to know when to do it? The dump transistors will pull the input pin to ground. If I monitor the paddle inputs and watch for it to go low, I know when the capacitors are reset and can start counting. Then I can send the input high at just the right time to trigger the POKEY.
This is super simple. And I made it work in a straightforward proof-of-concept. Here's the circuit:
The diode stops output PIN 3 from pulling down input on PIN 2. I want the dump transistor inside the POKEY to do the pulling. The proof-of-concept code is just some level checking and delays. This code can be used to reliably create readings from 1 to 227. Code 228 is made by just doing nothing, although to transition between 227 and 228 could be jittery because of the code trying to sync back up with the POTGO signal. A software PLL might be a way forward.
#include <Arduino.h>
void setup()
{
pinMode(3, OUTPUT);
pinMode(2, INPUT);
// try to charge up the POT capacitor until it takes
while (digitalRead(2) == LOW)
{
digitalWrite(3, HIGH);
delayMicroseconds(64);
digitalWrite(3, LOW);
}
// wait until dump transistor is activated
while (digitalRead(2) == HIGH)
{
}
}
void loop()
{
//trial and error on logic analyzer to get PADDLE(0)=1 despite a second late pulse
delayMicroseconds(2190); // count up until dump transisstor is released
delayMicroseconds(6350*2); // delay 100 line groups
delayMicroseconds(636*2+63*5); // delay 10 & 1 line groups
// charge up POT capacitor
digitalWrite(3, HIGH);
delayMicroseconds(63);
digitalWrite(3, LOW);
// wait until dump transistor clears cap with some debounce
while (digitalRead(2) == HIGH)
{
}
while (digitalRead(2) == HIGH)
{
}
}