RAM EXPANSION UNITS FROM COMMODORE DESIGNED FOR COMMODORE 128
REU 1700
Expands RAM up to 128kB (so, computer has 256kB RAM)
This expansion has two BANKS to access (0 and 1).
REU 1750
This model expands RAM up to 512kB (so, computer has 640kB).
Also this model has BANKS to access, in this case 8 (0 - 7)
Both modules has free one socket on board which is used in Commodore 128 as External function ROM.
From Commodore is else one model which can be used also on Commodore 64.
It's REU 1764, 1750 Clone.
Expands RAM up to 256kB, in case of Commodore 128 it allows to access by computer 384kB RAM.
This REU has 4 banks (0 - 3) to access.
Sometimes you can find modifications of this model which expands RAM up to 512kB.
More clones, expanding more memory exists, e.g. CMD's REU1750XL which expands RAM up to 2MB, also, own made by users of Commodore 128. Also on new devices is possible to set REU in range 128kB to 16MB (e.g. 1541Ultimate).
Creative Micro Designs RAMDrive
by WTE
Very smart and handy device ca be used as "portable HDD"
NiCd batteries backuped
SuperCPU compatibility: not compatible
Size: 1 or 2 MB RAM
Format: supports mostly the same partition types than the
RAMLink (1541, 1571, 1581, native)
Optional: additional use of the memory of a REU
OS: RD-DOS / JiffyDos replaces original C128/C64 ROMs
RTC (real time clock): no
Swap keys: yes (8/9)
REU possibilities of expanding RAM
Also, is needed to say that REU has also limitations.
Commodore 128 is 8-bit (best ever made) computer and it gives for this only 256 BANKS.
($00 - $ff / 0 - 255)
It makes the top of enlargement of RAM to 16384kB (16MB).
In BASIC V7 is possible to access only 16 BANKS (0 - 15), so, for BASIC is maximal accessible REU 1024kB (1MB), all more is unaccessible.
In assembler is possible to access full range of 16MB REU 'cause it's no problem to set any value to bank in one byte ($00 - $ff). But that's maximum, 16384kB and no more.
REU FREE SOCKET FOR OWN 32kB EPROMS
As you can see on picture, when you uncase REU, there is EPROM socket (highlighted by red on the picture).
Commodore 128 has also one EPROM socket on motherboard. Use both is the same way.
You can use this socket for EPROMs limited by capacity 32kB, of course, if you use switcher, there han be e.g. two chips.
That all for writting possibilities of REUs, now, how PROGRAMMING REU?
PROGRAMMING REU
Basic V7
In Commodore 128 BASIC are these commands for working with REU:
FETCH
STASH
SWAP
FETCH bytes,destination address, REU address, REU bank (works in 1MHz mode only)
- this command transfers data from REU to RAM
bytes: set how many bytes you want to get (0 - 65535)
destination address: set to where in RAM send bytes from REU (0 - 65535)
REU address: set address where are located data in REU (0 - 65535)
REU bank: set the REU bank from which will be data transfered to RAM (0 - 15)
- REU bank has these limitations in case of expansion module:
0 - 1 = C1700 REU (128kB)
0 - 7 = C1750 REU (512kB)
0 - 3 = C1764 REU (256kB)
if you have other variants, larger size etc. you can always recalcutate maximal BANK number (but limitation is BANK 15). Recalculating is simple REU SIZE / 64 and result is maximal number of BANKs.
STASH bytes, source address, REU address, REU bank
- this command transfers data from RAM to REU
bytes: set how many bytes you want to send (0 - 65535)
source address: set from where in RAM send bytes to REU (0 - 65535)
REU address: set address where to save data in REU (0 - 65535)
REU bank: set the REU bank to which will be data transfered from RAM (0 - 15)
- REU bank has these limitations in case of expansion module:
0 - 1 = C1700 REU (128kB)
0 - 7 = C1750 REU (512kB)
0 - 3 = C1764 REU (256kB)
if you have other variants, larger size etc. you can always recalcutate maximal BANK number (but limitation is BANK 15). Recalculating is simple REU SIZE / 64 and result is maximal number of BANKs.
SWAP bytes, RAM address, REU address, REU bank
- this command swaps data between RAM and REU
bytes: set how many bytes you want to swap (0 - 65535)
RAM address: set RAM address where are data to swap (0 - 65535)
REU address: set REU address where are data to swap (0 - 65535)
REU bank: set the REU bank in which are data to swap (0 - 15)
- REU bank has these limitations in case of expansion module:
0 - 1 = C1700 REU (128kB)
0 - 7 = C1750 REU (512kB)
0 - 3 = C1764 REU (256kB)
if you have other variants, larger size etc. you can always recalcutate maximal BANK number (but limitation is BANK 15). Recalculating is simple REU SIZE / 64 and result is maximal number of BANKs.
Assembler
In assembler is programming REU very similar with VDC programming.
The REUs provide additional RAM for the C128. 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 C128 with it's 16-bit address space. It has to be transferred from an to the main memory of the C128. For that purpose there is a built in RAM Expansion Controller (REC) which transfers memory between the C128 and the REU using Direct Memory Access (DMA). It can also be used for other purposes.
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 C128. They can be read and written to like VIC-IIe and SID-registers.
$DF00: STATUS REGISTER
(read only)
Bit 7: INTERRUPT PENDING (1 = interrupt waiting to be served)
Bit 6: END OF BLOCK (1 = transfer complete)
Bit 5: FAULT (1 = block verify error)
Set if a difference between C128- and REU-memory areas was found
during a compare-command.
Bit 4: SIZE (1 = 256 KB)
Seems to indicate the size of the RAM-chips. It is set on 1764
and 1750 and clear on 1700.
Bits 3 - 0: VERSION
$DF01: COMMAND REGISTER
By writing to this register RAM transfer or comparision can be
executed.
Bit 7: EXECUTE (1 = transfer per current configuration)
This bit must be set to execute a command.
Bit 6: reserved (normally 0)
Bit 5: LOAD (1 = enable autoload option)
With autoload enabled the address and length registers (see
below) will be unchanged after a command execution.
Otherwise the address registers will be counted up to the
address off the last accessed byte of a DMA + 1,
and the length register will be changed (normally to 1).
Bit 4: $FF00
If this bit is set command execution starts immediately
after setting the command register.
Otherwise command execution is delayed until write access to
memory position $FF00
Bits 3 - 2: reserved (normally 0)
Bits 1 - 0: TRANSFER TYPE
00 = transfer C128 -> REU
01 = transfer REU -> C128
10 = swap C128 <-> REU
11 = compare C128 - REU
$DF02 - $DF03: C128 BASE ADDRESS
A 16-bit C128 - base address in low/high order.
$DF04 - $DF06: REU BASE ADDRESS
This is a three byte address consisting of a low and
high byte and an expansion bank number.
Normally only bits 2 - 0 of the expansion bank are valid
(for a maximum of 512 KByte), the other bits are always
set. This must be different if more than 512 KByte are
installed.
$DF07 - $DF08: TRANSFER LENGTH
This is a 16-bit value containing the number of bytes to
transfer or compare.
The value 0 stands for 64 Kbytes.
If the transfer length plus the C128 base address exceeds
64K the C128 address will overflow and cause C128 memory
from 0 on to be accessed.
If the transfer length plus the REU base address exceeds
512K the REU address will overflow and cause REU memory
from 0 on to be accessed.
$DF09: INTERRUPT MASK REGISTER
Bit 7: INTERRUPT ENABLE (1 = interrupt enabled)
Bit 6: END OF BLOCK MASK (1 = interrupt on end)
Bit 5: VERIFY ERROR (1 = interrupt on verify error)
Bits 4 - 0: unused (normally all set)
$DF0A: ADDRESS CONTROL REGISTER
Controlls the address counting during DMA.
If an address is fixed, not a memory block but always the same
byte addressed by the base address register is used for DMA.
Bit 7: C128 ADDRESS CONTROL (1 = fix C128 address)
Bit 6: REU ADDRESS CONTROL (1 = fix REU address)
Bits 5 - 0: unused (normally all set)
How To Recognize The REU?
Normally the addresses between $DF00 and $DF0A are unused. So normally if values are stored there they get lost. So if you write e.g. the values 1,2,3,... to $DF02..$DF08 and they don't stay there you can be sure that no REU is connected. However if the values are there it could be because another kind of module is connected that also uses these addresses.
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.
Prefered is to let the user choose if and which REU banks shall be used.
Simple program for read/write from/to REU:
.var status = $df00
.var command = $df01
.var c128base = $df02
.var reubase = $df04
.var translen = $df07
.var irqmask = $df09
.var control = $df0a
.pc=$1300 "REU WRITE"
start:
lda #00
sta control
lda #$00
sta c128base
lda #$20
sta c128base+1
lda #00
sta reubase
lda #$c0
sta reubase+1
lda #$02
sta reubase+2
lda #$00
sta translen
lda #$10
sta translen+1
lda #%10010000
sta command
rts
.pc=$1400 "REU READ"
lda #00
sta control
lda #$00
sta c128base
lda #$20
sta c128base+1
lda #00
sta reubase
lda #$c0
sta reubase+1
lda #$02
sta reubase+2
lda #$00
sta translen
lda #$10
sta translen+1
lda #%10010001
sta command
rts
*this program saves $1000 bytes from $2000 to $c000 in REU bank $02 and transfer it back