Friday, August 18, 2017

Solid-state Joystick

This is not something that I was expecting to be doing this year, but sometimes opportunities just pop up.

Early in the year, one of my colleagues, Damian, showed me one of these strain-gauge solid-state joysticks that they were using as part of the undergraduate engineering curriculum:

Their goal was to teach the students how to read strain-gauges.  But I immediately saw the applicability for making a no-moving-parts super-robust joystick for the MEGA65 and all other retro computer users.

Strain-gauges measure the strain on an object, by effectively measuring the stretching or compression force on the sensor caused by deformation of the object under strain (apologies to any mechanical engineers who are probably cringing at my description here).  All you have to do is to try to move the joystick handle, and the gauges will pick up the minute deformation of the steel plate it is connected to.  This is how those touchpoint pointing devices that you find in the keyboards of some laptops work.

Seeings as we have only one sick TAC2 joystick in the lab, and haven't really seen anything worth replacing it with on the market, we decided to explore designing a MEGA65/C64/Amiga/Atari compatible joystick around this concept -- especially since we had working hardware on hand to work with.

The teaching unit was designed to work with an Arduino, so I went and bought one this morning, and between meetings today hacked up a tiny Arduino sketch to interface to it.  I figured we only needed 2 of the 4 sensors, since they are at 90 degrees to each other.  It turned out that all we needed to do was to tare two of the sensors, i.e., subtract their value when the stick is standing un-touched, and then monitor the sign and magnitude of deviation from zero for the two sensors, and we could quite easily detect all 8 directions with good reliability. The lack of travel makes this a potentially very fast joystick for those games where you have to toggle rapidly from side to side.

The only caveat with using only two sensors instead of four is that we can't then interpret a tap on the top of the joystick. While such tap detection is a fun idea, for a retro gaming joystick, it isn't really required, as you can't tap a stick while yanking it around at high speed.  Thus we will still need to have a real fire button, but it does mean we can save on sensors and the associated amplification circuitry for reading them.

Current idea for the fire button(s) is to have a fire button which interrupts an infra-red sensor, like a shop door sensor.  That way, there will be the absolute minimum of moving parts, short of making the fire button touch-sensitive -- but that doesn't feel right.

Otherwise, the biggest challenge we saw was the drift in readings, which means that there is a need for recalibration.  This is a well known problem with the Touchpoint devices, as they have to fairly frequently recalibrate. This occurs automatically, and shouldn't be a big problem, but we will have to implement the algorithm for this. 

Apparently a common approach is to look for a steady reading with very little variation as an indication of it being stationary, and recalibrate to that point. This would be quite easy to implement.

Otherwise from an electronic perspective, we just need to add the joystick port signalling, which is fairly easy to do.

Simultaneously, we can also start looking at laying out the important parts of the Arduino and the strain gauge shield onto a single PCB that can fit over the metal base plate.  We have a student who will hopefully look at this as part of their project, but I might also talk to Damian about this.  

I would also like to add PWM output onto the pot lines, so that we can have it support 1351 mouse mode, using the proportional/analog nature of the strain gauges to allow the joystick to work as a pointing device for GEOS, so that you don't need to swap joystick and mouse all the time.

Then the plan is to design the plastic case and knob for it, and make necessary adjustments to the metal base plate, so that we can assemble these into complete working joysticks, and indeed have a design that is feasible to produce in modest quantities. Maybe we will design it for a clear case, so that the no-moving-parts insides are visible. Either that or traditional Joystick Black.

Either way, if we like the result, and they are robust enough in practice, we might look at making them available to folks if there is sufficient interest.


  1. Be aware that the Commodore 1351 does not generate analog, or more precisely, continuous signals. It contains a special purpose chip that senses when the SID empties its buffer, then charges it with a full 5V for a period that is proportional to the mouse position.

    Allthough the end result is a PWM of approximately 2KHz, it is synchronized with how the SID measures the POT lines. The reason of this is probably accuracy.

    If you generate a high frequency PWM signal with an Ardiono and smooth it with a capacitor, question is wether you will achieve the same accuracy as the 1351. If not, you should be able to use the same approach as the 1351 with an Arduino, connecting the analog inputs to the POT lines in addition to a digital output. It might take a little research for how to detect that the SID is emptying its buffer.

    1. Hi Daniel,

      I knew that it generated a PWM signal, but I didn't realise it worked out when the SID measured the POT lines. This has implications not only for the solid state joystick, but how we measure the POT lines on the MEGA65, to make sure that a 1351 mouse will still work.
      Do you have any more information on this, or would you like to help us make either the 1351 emulation in the joystick, or work on the M65 side of the interface?


    2. The section "Inners" in on this page has a quite informative description:

      As for helping: I don't have any FPGA demo boards and neither FPGA programming skills. Perhaps I can help you with the joystick, perhaps starting with some oscilloscope measurements on the control point and as a second step, perhaps connect an Arduino to the control port and see if I can send some mouse position data to the SID.

    3. Hello,

      Yes -- both those would be extremely helpful. If you can get an Arduino sending the right data for the 1351 mouse driver to behave solidly with it, that would be excellent.


    4. Daniel: Can you please drop me an email, so we can coordinate this (we also have a student on our side who can help with some parts of it)?