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 23, 2025
Arduino MIDI Atari Paddles
Finally, I get to the point where I can do something vaguely musical with my Atari 2600 Controller Shield PCB. This turns it into a simple MIDI CC controller using the Atari paddles. https://makertube.net/w/dgK7y73KfC1SWc5z2wsJ6x Warning! I str…
Finally, I get to the point where I can do something vaguely musical with my Atari 2600 Controller Shield PCB. This turns it into a simple MIDI CC controller using the Atari paddles.
Warning! I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!
These are the key Arduino tutorials for the main concepts used in this project:
I've re-implemented my pot averaging code as a reusable object again but this time I've split it out into its own header file implementation. I've recreated the complete code below. This can be saved in a header file for simple reuse in other code.
private: int potpin; unsigned avgepotvals[AVGEREADINGS]; unsigned avgepotidx; unsigned long avgepottotal; };
One trick I've used (or at least, believe I've used - I'm not really a C++ person) is the use of a virtual function avgeReader(). By default this implementation calls straight out to the standard Arduino analogRead() function, but by being virtual means that it is possible to create a new class based on this one that can override that function with a bespoke routine.
This is what I've done to link this to the atariAnalogRead() function from my previous code as shown below. Note that, as I understand things, constructors aren't inherited, so a new constructor is required to link back to the base class's original.
class AtariPot : public AvgePot { public: AtariPot (int potpin) : AvgePot (potpin) {}
I can then set up four instances of this new AtariPot class for each of the paddle controls.
AtariPot *atariPot[NUMPADS];
void setup() { for (int i=0; i<NUMPADS; i++) { atariPot[i] = new AtariPot(pad_pins[i]); } }
Reading each atari pot is then just a case of calling the correct function for each instance.
void loop() { for (int i=0; i<NUMPADS; i++) { val = atariPot[i]->avgeAnalogRead() >> 3; } }
I'm shifting the result >> 3 to reduce the 10 bit value to a 7 bit value for use as a MIDI CC. This takes the range 0..1023 down to 0..127.
There is a table at the start that defines which MIDI CC message corresponds to which paddle controller. By default, I've used the following:
int midiCC[4] = { 0x01, // Modulation wheel 0x07, // Channel volume 0x0B, // Expression control 0x10, // General purpose control 1 };
Find it on GitHub here.
Closing Thoughts
I'm not sure quite how practical using Atari paddles for a MIDI controller really is, but that hasn't stopped me before and it hasn't stopped me now.
The video shows two paddles controller modulation and volume for a MiniDexed. So it does appear to work.
I've still a few other odds and ends I want to try:
It would be interesting to see how this contrasts with the simpler step of using a resistor to create a potential divider from the paddle as described in the original Atari 2600 Controller Shield PCB Build Guide. It would probably work fine too and would be a lot simpler in code terms.
I still want to do something with the Atari keypads!
I must admit there is also a part of me thinking that if I could find some paddle controllers that were perhaps no longer fully functional, I would be able to take them apart and stick a small microcontroller in the paddle housing itself...
No comments:
Post a Comment