I made an I2C module for RC2014 as I wanted to connect some of the many available modules that are available now to use with the Arduino and Raspberry Pi.
The module uses the PCF8584. The DIP version is no longer manufactured but can be still sourced in eBay. I used an ATMEL ATF150x CPLD for the decode logic to tighten the I/O address region and also to add some latches to control an I2C chipset reset line/error LED. It meant that I got to play with CPLDs for the first time but also keep the chip count down.
I hacked polling based drivers using SCC’s excellent monitor program to upload in intel hex, execute and debug. I’ve had success with master transmit and master receive commands with 5V compatible I2C modules:
I also connected an ATTINY45 to convert PS/2 keyboard serial to the I2C bus (a mashup of Sparkfun WIG-08652 and TInyWireS). The aim eventually is to hack the AVR on a retro style Clueboard keyboard to communicate directly on I2C. I2C carries the PS/2 make/break protocol commands rather than converting to ASCII (this is done on the Z80).
I got lucky with the PCB (based on the RC2014 module template) with no rework needed, including the In System Programming for the CPLD. In hindsight I should have brought out the PCF8584 reset line on a header because the OLED module also needs to be reset (I used a MCP2308 GPIO line to reset the OLED as a work around). I also chose a resistor footprint that was too small but I’m counting this as a win for my first PCB in over 20 years.
Although polling the RTC/keyboard every 100ms is not very efficient, the OLED now displays the time and most alphanumeric characters (including shift key functionality).
The only quirk remaining is that the PCF8584 seems to deviate from the data sheet when finishing a master transmit/receive. In the receive case, the PC8584 needs a double write of the control code to terminate the last byte. In both transmit and receive the I2C bus is note released unless I write a dummy byte to the PCF8584 data register.
I’m wondering if this behaviour is some kind of timing issue as none of the example code I’ve found includes these workarounds apart from a hint in an Irix I2C driver. Has anyone seen similar behaviour on other parallel chips connected to the Z80 bus where they are sensitive to bus/coding timing? (I noted the data sheet specified minimum of 6 clock cycles between reads/writes to the PC8584 but I think there are enough operations in the code not to breach this constraint).
PCF8584_DAT EQU 0xC0
PCF8584_CSR EQU 0xC1
…
; tell PCF8584 that this is the final byte to read so it NAKs
LD A, PCF_ESO
OUT (PCF8584_CSR), A ; PCF8584 ignores this write
OUT (PCF8584_CSR), A
…
; PCF8584 won’t release bus without a dummy write to the data register
LD A, 5 ; dummy address "2 << 1 | 1"
OUT (PCF8584_DAT), A
; Release the I2C bus
LD A, PCF_PIN | PCF_ESO | PCF_STO | PCF_SACK
OUT (PCF8584_CSR), A