I want to contribute to the mailing list on the software side. So I send you a description of the programming of the 17xx RAM expansion units. I sent this already a week ago but it got lost during the problems with the old mailing list address. In the meantime there has already been posted some information about REUs, but my description is a bit different and contains more detailed information, so I thought I nevertheless send it to you.
The following is based on the Commodore 1764 user's manual (german version) and my own experiences programming the 1764 Ram Expansion Unit (REU).
1) External RAM Access With REUs
The REUs provide additional RAM for the C64/128. Three types of REUs
have been produced by Commodore. These are the 1700, 1764 and 1750 with
128, 256 and 512 KBytes built in RAM. However they can be extended up to
several MBytes.
The external memory can not be addressed directly by the C64 with it's
16-bit address space. It has to be transferred from an to the main
memory of the C64. For that purpose there is a built in RAM Expansion
Controller (REC) which transfers memory between the C64 and the REU
using Direct Memory Access (DMA). It can also be used for other
purposes.
2) RAM Expansion Controller (REC) Registers
The REC is programmed by accessing it's registers, that appear memory
mapped in the I/O-area between $DF00 and $DF0A when a REU is connected
through the expansion port of the C64. They can be read and written to
like VIC- and SID-registers.
Another problem is the recognition of the number of RAM banks (64 KByte units) installed. The SIZE bit only tells that there are at least 2 (1700) or 4 (1764, 1750) banks installed. By trying to access & verify bytes in as many RAM banks as possible the real size can be determined. This can be seen in the source to "Dynamic memory allocation for the 128" in Commodore Hacking Issue 2.
I personally prefer to let the user choose if and which REU banks
shall be used.
4) Simple RAM Transfer
Very little options of the REU are necessary for the main purposes of
RAM expanding.
Just set the base addresses, transfer length and then the command register.
The following code transfers one KByte containing the screen memory ($0400..$07FF) to address 0 in the REU:
I think that this subset of 17xx functions would be enough for a
reasonable RAM expansion. However if full compatibility with 17xx REUs
is desired also the more complicated functions have to be implemented.
5) Additional Features
If RAM between $D000 and $DFFF or character ROM shall be used it is possible to delay the execution of the command by storing a command byte with bit 4 ("FF00") cleared. The command will then be executed by writing any value to address $FF00.
Example:
Comparing memory areas is as fast as transfers. (Comparison is stopped once the first difference is found.)
Swapping memory is only half as fast, as for every bytes two C64 memory
accesses (read & write) are necessary.
7) Interrupts
By setting certain bits in the interrupt mask register IRQs at the end
of a DMA can be selected. However as the CPU is halted during DMA it
will always be finished after the store instruction into the command
register or $FF00. So there is no need to check for an "END OF BLOCK"
(bit 6 of status register) or to enable an interrupt.
8) Executing Code In Expanded Memory
Code in external memory has always to be copied into C64 memory to be
executed. This is a disadvantage against bank switching systems. However
bank switching can be simulated by the SWAP command. This is done e.g.
in RAMDOS where only 256 bytes of C64 memory are occupied, the 6 KByte
RAM disk driver is swapped in whenever needed. Probably too much
swapping is the reason for RAMDOS to be not really fast at sequential
file access.
9) Other Useful Applications Of The REU
The REC is not only useful for RAM transfer and comparison.
One other application (used in GEOS) is to copy C64 RAM areas by first transferring it to the REU and then transferring it back into the desired position in C64 memory. Due to the fast DMA this is about 5 times faster than copying memory with machine language instructions.
Interesting things can be done by fixing base addresses. Large C64 areas can be filled very fast with a single byte value by fixing the REU base address. Thus it is also possible to find the end of an area containing equal bytes very fast e.g. for data compression.
Fixing the C64 base address is interesting if an I/O-port is used, as data can be written out faster than normally possible. It would be possible to use real bitmap graphics in the upper and lower screen border by changing the "magic byte" (highest by the VIC addressed byte) in every clock cycle during the border switched off.
Generally the REC could be used as graphics accelerator e.g. to
copy bitmap areas or to copy data fast into the VIC-addressable
16 KByte area.
10) Comparision Of Bank Switching and DMA
When comparing bank switching and DMA for memory expansion I think DMA
is the more comfortable methode to program and also is faster in most
cases. The disadvantage with code execution not possible in external
memory could be minimized by copying only the necessary parts into C64
memory. Executing the code will take much more time than copying it
into C64 memory.
Richard Hable