Introduction
6522 Shift Register -
Shift in under PH02 clock
In this article I share my findings in the configuration and use of the Shift Register in Mode 2. The approach to this, the code and methods used may appear convoluted, but I have learned so much in the process. [6522 configuration and usage, 74165 and 7474 usage, Arduino interrupt programming].
Hopefully you will find some of this article interesting and maybe even useful.
SR Mode 2 -
Shift Serial Data in under control of PH02
The shift rate is a direct function of the system clock frequency.
CB1 becomes an output which generates shift pulses for controlling external devices.
The shifting operation is triggered by either reading from or writing to the Shift Register.
Data is shifted, first into bit 0 and is then shifted into the next higher order bit of the shift register on the trailing edge of each PH02 clock pulse.
After 8 clock pulses, the shift register interrupt flag (IFR) will be set, and the output clock pulses on CB1 will stop. At this point the data is held in the Shift Register. Another read of the Shift Register is needed to retrieve the data to the CPU. Doing this read clears bit 2 of the IFR, and generates another 'shift-in' sequence, after which, bit 2 IFR is set again.
The
challenge
Having work through the majority of the 6522 operating modes, the 'shift serial data in' mode posed its own challenge to me. Generating outputs from the 6522 can be monitored on an oscilloscope, or by using LEDs connected to the various ports. Generating parallel input data on Port A or B can be achieved manually. Getting the 6522 to generate a shift-in clock together with generating a 'trigger pulse' for an external device to respond with providing serial data to the 6522 was quite a challenge.
The
experiment
Part of the experiment uses the idea put forward by Garth Wilson at:
http://wilsonminesco.com/6502primer/potpourri.html#22_SR_INnOUT
This uses a 74165 (parallel to serial shift register), to provide serial data and a 7474 (Dual D-Type Positive Edge Triggered Flip-Flops). Garth helpfully describes the rationale for using the 7474 to delay the data to ensure the data is shifted from the 74165 to the 6522 correctly.
The first experiment I tried was to manually configure the 74165 and wrote a short piece of code to read one byte into the 6522 Shift Register. This worked well and as expected.
The second experiment I tried was to use an Arduino board to generate 8-bit parallel data, connected to the 74165. The Arduino was used in an interrupt mode, triggered by a low pulse from the 6522, to generate an 8-bit byte to load into the 74165. After this operation, the 6522 is used to shift in the data and store the data in memory, and write out to LEDs connected to Port A.
The Block
diagram:
The circuit
diagram:
For clarity, the circuit diagram omits connections to power and many connections associated with the 6522 VIA and the Arduino.
The 6502
assembly code notes & process flow:
6522
CB1 used to generate the clock signal (8-bits)
CB2 used as the serial shift input from the 74165 shift register
CA2 used to enable the 74165 for loading data, and to trigger the Arduino to load the 74165 with 8-bit parallel data (by taking CA2 -ve).
CA2 defaults to HIGH, enabling the 74165 output mode.
Registers used:
ACR - Auxillary Control Register, write $08 Mode 2 = Shift in under PH02 control
IFR- Interrupt Control Register, write $7F, Clear
IER - Interrupt Enable Register, write $84, Set Shift Register IRQ
SR - Shift Register, read SR, generates shift clock on CB1, reads in data on CB2
PCR - Peripheral Control Register, write $0A, sets 'Pulse Output' mode - CA2 normally High
DDRA - Data Direction Register A, write $FF, set Port A as outputs
IRA - Input/Output Register A, write $xx, sets data on Port AProcess flow
* Set up DDRA, IFR, IER, ACR, PCR
* Use the PCR to generate -ve pulse on CA2, enables the 74165 for loading, 'triggers' the Arduino to output data to the 74165 (loads the data into 74165)
* CA2 returning High enables serial o/p from 74165
* Write $00 to the 6522 SR, clears the SR and an 8-bit clock stream is generated on CB1, when complete the IFR bit 2 is set, the /IRQ line goes Low. The clock stream, applied to the 74165, clocks the parallel data on the 74165 to the 6522 Shift Register.
* To get the data from the SR to the CPU, read the SR. This resets the IFR and /IRQ goes High. Reading the SR also generates another 8 clock pulses. When complete, the IFR is set and /IRQ goes Low.
* A clear of the IFR is needed, this also sets /IRQ High.
* Store the read data value in memory and write data to port A outputs.
* Return to monitor [monitor re-entry address = $E070]
Oscilloscope
traces:
Top trace: CA2 line drops -ve to trigger Arduino and enable 74165 for loading Middle trace: Arduino bit-7 indicates when the Arduino data byte is complete for 74165 loading Lower trace: CB1 Shift Clock pulses from 6522 |
Top trace: CA2 - after 74165 data loaded, CA2 returns High to allow 74165 serial output Middle trace: CB1 Shift Clock pulses from 6522 Lower trace: CB2 Serial data from 74165/7474 to 6522 Shift Register In (data value $FA). The second set of 8 clock pulses is the 6522 response from executing a read of the 6522 SR. |
Zoomed in copy of previous display: Top trace: CA2 - after 74165 data loaded, CA2 returns High to allow 74165 serial output Middle trace: CB1 Shift Clock pulses from 6522 Lower trace: CB2 Serial data from 74165/7474 to 6522 Shift Register In (data value $FA). |
6502 Serial Terminal Screen display (using 'screen' on RaspberryPi)
Running the 6502 code at $1000 runs through the 6502 code below once. Running this routine 4 times shifts in the 3 data byte values held by the Arduino ($FA, $FB and $FC). These values are stored in zeropage RAM at address $0016. The values are overwritten each time the 6502 routine is run.
Conclusions:
This experiment (for me) was quite challenging, and I learned so much doing the research, writing the 6502 and Arduino code and interpreting the oscilloscope displays to work out the various signal timings to ensure all the different elements worked together. Although unlikely to be a useable and practical way of getting data into the 6502 RAM, I envisage that with minor modification it would be possible to load large quantities of data from the Arduino to the 6502 computer.
Forgive me if I missed a detail here but I actually just implemented SPI mode 3 using the 65C22 shift register, driving a DAC in my case, and I have it working currently without enabling the interrupt for the shift register, and thus, saving the clock cycles to push/pop the PC and so on and jump to and from the interrupt handler. I also replaced the polling loop for IFR with some nops :P To my delight, and surprise, it actually did get slightly faster -- around 8 microseconds in my case, with a system clock of 12 MHz.
ReplyDeleteHere's the transfer routine I have currently: https://gist.github.com/sci4me/3b0261ee656bbb04cf8eb8fb8873a9ef