That Ain't Right
I implemented a simple program to read the rotary controller by polling the joystick port in a tight loop. I implemented the program for the CoCo3, and used a CoCo3-specific video mode. After clearing the screen, I used the inputs from the controller to form a bitmask which I then used to change the color for palette entry 0. This was intended to provide some basic feedback as a first step before going forward.
Unfortunately, I quickly noticed that I was only seeing three colors when I turned the knob on the controller. I tweaked the code a bit, only to find that in some cases I was down to only two colors in the sequence. After re-verifying that the controller hardware still worked with the earlier demo (on a CoCo1), I even tried a different CoCo3. Still, the issue remained. In an effort to verify the software itself, I transformed the program into something that would run on any CoCo. Then I could test the program on all the same hardware that ran the other demo.
Back To Basics
I changed to using a text mode for the output. Instead of changing a color, I used the bitmask derived from the controller inputs to generate a number character on the screen. This allowed me to better understand the exact sequence of values being detected by the software.
At this point, I just fiddled with the controller and watched the numbers change. After a while, I switched from the rotary controller to the standard joystick instead. Eventually I was able to understand what I was seeing -- the second axis almost always read the same as the first axis, with some exceptions depending on a few tweaks here and there.
Wait For It
The CoCo reads the joysticks using a DAC and a comparator. One of the comparator inputs is selected using a linear switch controlled by one of the CoCo's PIAs. In order to read two axes, the switch has to be changed to select the second axis. In my existing code, switching the axis is followed by setting a new DAC value before checking the comparator.
The rotary controller outputs are digital, so only one comparator check is needed per access. Also, the same DAC value is used for the comparisons on both axes. Consequently, I was checking the comparator immediately after switching to the second axis. This seems to work fine on the CoCo1, but on the CoCo3 it is prone to failure. Inserting a few NOP instructions seems to stabilize that situation. A dummy set of the DAC value would probably give enough time for the comparator to stabilize as well.
With that issue resolved, I extended my test program to use color and more screen real estate. This makes it easier to visualize and track the states as they are read from the rotary controller. It also confirms that switch bounce is a problem, as demonstrated in the video clip above. Figuring-out how to deal with that will probably be my next step -- stay tuned!