PSCD32 Development Diary

B.C. Kid

I was sold these magic beans by a wizard who said if I plant them I can grow a computer. Thank you, guy from S.S. Radio. Yellow, purple, black = 47 Ohms. It's a nice shop, the proper real deal. Except smoking is banned here in shops so it (thankfully) doesn't have the deadly ambience of Hamlet cigarettes I'd first associate with Amiga repair. These resistors cost 0.01p in bulk, 1p in a set of 500, 4p from a supplier, 7p from a hobby electronics shop... and 20p when you go to a old man's audio hi-fi repair shop and ask if he sells components. But I got what I wanted, and it flippin' heckin' works! B.C. Kid is a dream with a Playstation pad. It's a port of a PC Engine game so its designed for two buttons originally. In the old days, you'd play it on an Amiga with a one button arcade stick with Up To Jump. The Amiga was mostly a one button machine even though the socket supports three buttons without any fuss, just nobody made controllers for it. And so nobody made games that supported it. I could plug in a Sega Master System pad and it'd work flawlessly with this game. The Mighty David Pleasance (former Joint Managing Director of Commodore UK) should have worked out a deal with Sega or something: when marketing the Amiga, ring up Sega and get them to sell him a few hundred thousand Master System pads. They're basically made of nothing, so how much could they cost? Stick one of those in every Amiga box! The Amiga would've had more two-button games, and everybody would've been happy. But then, I suppose the Amiga was at its strongest when it was providing an arcade-perfect experience with games like Rod-Land and Volfied... Don't plug in a Mega Drive pad though, whatever you do. You'll make a mess. Here's the PSCD32 with the 47R resistor installed across the FIRE2OUT/DATAOUT line. Continually surprised that I can plug 2018-tech into 1987-tech without either of them exploding. Conservative design is important! And double checking, and lots of paper notes. Speaking of.

Notes on these resistors

For UDLR: as far as I know the Amiga can't send any big voltage or current to them. There is a pull up voltage that must be defeated in order to register a zero. A dumb switch that connects directly to ground is sufficient and safe, this is what a Zipstik and a SMS pad does after all. I didn't measure the current flow there though. I expect it'll be the 5V supply through the 4.7k pullup = 1mA current. Standard and safe there. Don't need to change my safety resistors. For the three fire buttons, they can be actively driven either way or held high-Z for reading. And I'm not sure about the high-Z. To read a second button or the right mouse, you have to set it to high and then read it. And from my experiments with the probes, it isn't very nice about it. Amiga Test Kit sets Fire2out's pin to high in order to receive a switch-low grounded response from the peripheral. I might need to 47R all the (potentially) bidirectional lines.

Clock this

I reduced the clock speed and now everything is failing. Weird how it only works when it's overclocked. Looking at the disassembly, some of my interrupts are 20-30 asm instructions long, but my interrupts are firing every 20 instructions. That's not going to work. I want to communicate with the PS2 pad at 200 kHz. 4MHz instruction frequency / 200 kHz SPI clock frequency = 20 instructions per SPI clock. So I -have- to use the overclocking mode to get sufficient reaction time, otherwise 4 MHz / 40 instructions = 100 kHz max clock which might be too slow for PS2 pad comms. The overclocking uses an internal 4X clock multiplier against the internal 8 MHz oscillator (there's two clock cycles per instruction, so that's where the 4 MHz comes from). So I multiply everything by four. I can still DOZE I think in order to reduce the main instruction clock, but the errata says DOZE is glitchy SOOOOO... maybe there's some other power saving clock method I can use that keeps the SPIs ticking as they ought to. But for now let's keep everything 32 MHzed. Working is better than not working.

CD32 Protocol Time

I'm going to need tea. And diagrams. Lots and lots of diagrams and tea. First, I need to identify what operations the Amiga is going to perform, and the responses it expects. The tables and diagrams from Gerd Kautzmann's CD32 controller page are a good start, but I'd like them in linear timing diagram form. Here it is. The diagram at the bottom shows the states of pins 5, 6 and 9 from the CD32 game port during a controller poll. • While 5 JOYMODE/FRAME is high, the controller acts as a two-button, closed-switch joystick. In this state, the state of Red and Blue are output from the controller immediately, at all times on pins 6 FIRE1OUT/CLOCKIN and 9 FIRE2OUT/DATAOUT. (I also just noticed that this pin is left floating if connected to a system that doesn't use pin 5 according to Kautzmann.) • When 5 JOYMODE/FRAME goes low, the shift register captures its inputs and presents the frozen Blue value on 9 FIRE2OUT/DATAOUT. Pin 6 FIRE1OUT/CLOCKIN becomes an input to the pad. • The output of pin 9 FIRE1OUT/DATAOUT is constant until a rising edge on pin 6 FIRE1OUT/CLOCKIN, where it cycles to the next button input in this order: Red, Yellow, Green, FF, Rew, Pause, 1, 0, 0, 0... • The shifting is terminated if 5 JOYMODE/FRAME rises, the shift register returns to loading mode, with instantaneous Red and Blue outputs on pins 6 FIRE1OUT/CLOCKIN and 9 FIRE2OUT/DATAOUT. My notes here show my plan. • Timer1 controls the quantized SPI communication and Attention framing to the PS2 pad. • SPI1 is triggered by Timer1's cycle to transfer single bytes to or from the PS2 pad. • Timer2 is a 1000Hz interrupt to ensure a rapid update of the directional output at all times. If JOYMODE is low, do not manipulate the fire buttons. • CN interrupt on 5 JOYMODE falling takes control of 6 FIRE1OUT/CLOCKIN and 9 FIRE2OUT/DATAOUT for shift communication. SPI2 may be used to perform the shift communication. If I do this, I have to remember the SPI module will shift out values MSB first. The issues here are I have to be able tell when the communication is finished - the Amiga may request an arbitrary number of shifted values: enough to read all the buttons, too many and retrieving the infinite zeroes, or abort after reading the colour buttons. I have to detect this event and transform back into a two-button joystick. There's two good sources of information I can use to learn more about the way the Amiga reads CD32 pads. Throughout these notes I've repeatedly said that Amiga software plays fast and loose with pretty much every part of the system, there are no standard ways to read the game port, keyboard or floppy drive, and if there were, programmers wouldn't use them in the pursuit of speed or plain ignorance. That is true, as far as I know, but for the later OS revisions for the A1200 and CD32 onwards, a module named lowlevel.library was included in ROM to allow the reading of the CD32 joypad. Documentation is here. I could disassemble this routine and see exactly what the Amiga attempts to do in the manufacturer-specified ideal reality. Another, much faster alternative would be to simply look at the source code to Amiga Test Kit (it's public domain). It'll have comments and stuff. It won't be the same as the Commodore library implementation, but since it's meant to test pads, it ought to be very close to the correct way to read real, existing pads, and it'll be compatible with the A500. Let's have a look.
/* Read gamepad button state of specified port using specified ciaa address. */ static uint32_t read_gamepad(uint8_t port, volatile struct amiga_cia *_ciaa) { unsigned int i, j; uint32_t state = 0; /* Pin 6 clocks the shift register (74LS165). Set as output, LOW, before * we enable the pad's shift-register mode. */ _ciaa->ddra |= CIAAPRA_FIR0 << port; _ciaa->pra &= ~(CIAAPRA_FIR0 << port); /* Port pin 5 enables the shift register. Set as output, LOW. Port pin 9 * is the shift-register output ('165 pin 9). Set it as input. */ cust->potgo = port ? 0x2f00 : 0xf200; /* Probe 7 buttons (B0-B6), plus 3 ID bits (B7-B9). * B7 = '165 pin 11 (parallel input A) = FALSE (pulled high) * B8+ = '165 pin 10 (serial input) = TRUE (pulled low) */ for (i = 0; i < 10; i++) { /* Delay for 8 CIA clocks (~10us). */ for (j = 0; j < 8; j++) (void)_ciaa->pra; /* Read the shift-register output (port pin 9). */ if (!(cust->potinp & (port ? 0x4000 : 0x0400))) state |= 1u << i; /* Clock the shift register: port pin 6 pulsed HIGH. */ _ciaa->pra |= CIAAPRA_FIR0 << port; _ciaa->pra &= ~(CIAAPRA_FIR0 << port); } /* Return the port to joystick/mouse mode. */ cust->potgo = 0xff00; _ciaa->ddra &= ~(CIAAPRA_FIR0 << port); return state; }
From this I can find that 6 FIRE1OUT/CLOCKIN is pulled low immediately before 5 JOYMODE is pulled low. The pad's output on 9 FIRE2OUT/DATAOUT is sampled by the Amiga at some point during the low phase of the clock cycle, after which it is immediately raised momentarily. This means we cannot rely on there being a falling edge present on the 6 FIRE1OUT/CLOCKIN line. This is important.