I've added code to interpret the left analogue stick deflection as directional input as well, because why not? My TESUN knock-off Dualshock-shaped USB PC pad has a similar function and it comes in handy. It was no big deal, just writing some conditions to compare the position of the stick against a threshold. There's no calibration or enabling required. (Though Sony's protocol does allow a command to be sent from a console to the pad to turn its Analog mode on.) My pad reading code checks for the normal identifier values of digital and analogue pads, and uses the same reading code for both as analogue pads are a superset of digital pads. For digital pads, the absent analogue sticks are assumed to be always centred. This means that I don't have to use a condition to distinguish between them further on in the code.
But, you know, it's a shame that the analogue sticks can't also act as a mouse. I mean... there's no reason why not... they just have to speak the protocol.
Converting A Microsoft Serial Mouse To Work On The Amiga by Jeff Easton
The mouse movement is encoded entirely differently than joystick input. It uses 'Quadrature encoding'. Quadrature encoding is a method for encoding bidirectional motion along one axis by using two signals. This image from dynapar.com puts it across really well.
In this image, A and B are two digital output pins from the Amiga mouse. When the mouse moves, A and B toggle up and down in a set, repeating pattern. If the mouse is moved in the opposite direction, the sequence is output in reverse order. There are four states to the sequence: 1,1, 0,1, 0,0, 1,0. Since one signal is changing at a time, this makes it a Gray code, as well, if I'm not mistaken.
There is a direct relationship between the physical motion of the mouse ball and the changing signals, as the ball rolls against axles within the mouse linked to slotted wheels with photodetectors that produce the encoded signals as the wheels turn. This means that if the mouse is moved faster, the sequence will advance faster.
In the Amiga mouse, there are two axes, horizontal and vertical, each requiring a pair of signal pins. These signals are output on the Down and Right pins for horizontal motion, and the Up and Left pins for vertical motion.
To emulate the action of an Amiga quadrature mouse, this sequence needs to be output on the directional pins of the 9-pin joystick cable as open-drain outputs. The two (or three) mouse buttons are the same as for the two-button joystick: switches pulled to ground.
The Amiga reads these autonomously - there are hardware counters within the guts of the Amiga for each pair of axes on each game port that increment or decrement their values automatically without CPU intervention. The running software only needs to read these counters and compare their values periodically to track mouse movements. (Or use the proper Commodore ROM drivers.)
This also explains why if you plug a joystick into the mouse port while in a GUI on the Amiga you can cause the mouse to jiggle slightly by moving the joystick around, and how you can cause it to move in lines or diagonals by twirling it around in circles.
That's pretty simple!
The job of the PSCD32 then is to read the deflection of the analogue stick, determine the speed the mouse should be moving, and output the forward or backward sequence on the appropriate directional pins at the correct rate to encode the correct motion. I'm not going to do anything fancy like read the right analogue stick and use it as mouse input while the left stick is joystick input: a DIP switch will control whether the PSCD32 is emulating a joystick or a mouse.
• Maintain a quadrature phase counter from 0-3 for each axis.
• Read the deflection independently for each axis.
• Implement a dead zone by aborting if the deflection is too little.
• Map the deflection to a movement rate.
• Increment or decrement the quadrature phase counter.
• Alter the output pins to correspond to the new phase.
The complete quadrature sequence of 4 states moves the mouse cursor by 2 pixels. This means that if you altered the quadrature state once every PAL frame (50 Hz), you'd end up with a cursor that moved only 25 pixels per second, which means the mouse would take over 12 seconds to travel across the full width of the screen. Therefore these quadrature phase outputs need to be updated at a rate on the order of thousands per second!
I'm going to make it so that my UDLR directional immediate update Timer is used to update the quadrature mouse emulation at a rapid rate in x0,000 Hz when the PSCD32 is in mouse emulation mode. The phase counters can be updated as rapidly as once per Timer tick. For slower updates, I'm going to have a furhter 'ticks before next quadrature advance' counter that indicates how many Timer ticks need to take place before the quadrature phase counter is incremented.
For example, rapid movement might have a quadrature update every 5 ticks. Slow movement might have a quadrature update every 50 ticks. There's a reciprocal relationship between time between ticks and mouse movement speed.
A man, a plan, a PCB, an Amiga, a mouse, Panama. Kinda.
And if you don't have an analogue controller, the D pad works just as well on either controller, as my software directly injects a constant deflection in the stead of the analogue stick when a direction is pressed.