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:
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)
{
}
}