ZX-Badaloc Reloaded
Implementing the ZX-Badaloc Clone into an FPGA
Z80-accessible I/O registers implemented in current release
ZX-Spectrum standard registers:
$FE (254): Keyboard / Tape / Speaker / Border color
Read:
D7
Always '1'
D6 Tape Ear
in
D5 Always '1'
D4:D0
Fully functional Keyboard from PS/2 data
Write:
D4 Speaker out
D3 Tape Mic out
D2:D0 Border Color
$1FFD (8189): ZX-Spectrum
128K +2A / +3 special mode register
Read:
D2:D0
Read back written data
D3 West Button
D7:D4 SW3:SW0
Write:
D0
Paging
mode. 0 = normal; 1 = +2A/+3 special paging
D3 disk motor (not implemented)
D4 printer strobe (not implemented)
Normal mode (D0 = '0'):
D1 Ignored
D2 High bit (A15) of rom_bank
Special mode (D0 = '1'):
D2:D1 Selects a paging mode out of four possible (see
the +3 documentation)
$7FFD (32765): ZX-Spectrum 128K Memory Control
Read / Write:
D5
1FFD / 7FFD Registers Lock: '1' = Locked (no further write access allowed)
D4
low bit (A14) of rom bank
D3 Video
Bank select
D2:D0
128K Ram Bank Select
ZX-Badaloc Custom Registers:
$0F (15): DMX / RDM control register: see DMX page for details
$1F (31): Kempston Joystick and SD-Card chip select
Read:
D7:D0
8 bit Kempston
Joystick out of 16 inputs provided by 74HC166 interface. LSB or MSB bank
selectable (see below)
Write:
D7:D4
If = '1010' the Kempston port will read the 8 MSB bits instead of the LSB
(default)
If = '1011' the Programmable Joystick registers are write-enabled in memory (32
bytes)
D1:D0 SPI Chip select
enable: "10" = sd_card 1, "01" = sd_card 2, "00" =
onboard M25P16 Flash chip select, "11" all
disabled
The first sd-card slot has been installed and successfully tested
$3F (63): SPI Interface Data Register
Read: 8 bit from selected
SPI device (see $1F register)
Write: 8 bit to selected SPI device (see $1F
register)
$5F (95): NMI Enable on RS-232 reception, RS-232 Status Register
Read:
D7:D4
Always read "0000"
D3 rs-232 TX
Status:
'0' = idle, '1' = register full (tx in progress)
D2
rs-232 Framing Error: '1' = Error
D1
rs-232 Overrun Error: '1' = Error
D0 rs-232 RX Status: '1' = Data is Available for read on port $7F
Write:
D7:D1
Not used
D0 NMI Enable when rs-232
data is received: '1' = Enabled
$7F (127): RS-232 (Female DB9 Connector) Data Registers
Read: 8 bit RS-232 RX
Register
Write: 8 bit RS-232 TX
Register
$24DF (9439): Rom Bank / Z80 Clock Select
Read / Write:
D7:D6 ZX-Badaloc
shadow ram rd/wr control: meaningless on this FPGA implementation: not
implemented
D5:D3
ZX-Badaloc high rom bank address select (A18:A16) - A15 and A14 come from 1FFD
and 7FFD standard registers
32 rom banks (16K each) can be selected into the 0-3FFF memory area combining
these 5 bits.
D2 Z80 Clock /
Screen / INT Doubler: '1' = Z80 Clock *2, INT = 100Hz, VGA 100 Hz instead of
50Hz
D1:D0
Z80 Clock Select: "00" =
3.54MHz; "01" = 7.08MHz; "10" = 14.16MHz; "11" = 21.25MHz
$34DF (13535): Various ZX-Badaloc control flags
Read / Write:
D7
Fastpage address space (see fastpage register): '0' = 0-$3FFF (standard); '1' =
$C000-$FFFF (new in this FPGA version)
D6 Custom Registers Lock
bit: '1' = Locked
D5 Context Switch
inibith: '1' = no context switch takes place on $66 (NMI Vector) opcode fetch
(see ZX-Badaloc documentation)
D4
Parallel Flash Write Enable (parallel flash is not used on this clone)
D3
Writing '1' Removes Context Switch. Always read as '0'
D2
Writing '1' Forces a Context Switch. Always read as '0'
D1
Further Z80 INT Frequency Doubler: '1' = Active (50 -> 100Hz or 100 -> 200Hz
depending on D2 of $24DF register)
D0
Spectrum Type: '0' = 48K; '1' = 128K (Video Timings)
NOTE: The context switch is a special ZX-Badaloc feature which swaps-in a custom ROM when an NMI is being serviced (opcode fetch at address $66). This enables the RS-232 or sd-card snapshots and other special features.
$44DF (17631): Custom Register Lock Disable and FPGA BootLoader Swap Out
Write:
Writing $AA
(170) resets bit D6 of $34DF register, reactivating WR access to all Custom
registers.
It also disables forever the VHDL-Coded Z80 bootloader rom from
address space 0 - $3FFF and activates the standard memory (for operating mode).
$54DF (21727): FASTPAGE control register
Read / Write:
D7
Paged-in memory Write Enable: '1' = enabled. When 'RAM' type is paged, writing
is always enabled
D6
Page-in enable: when '1', the selected 16K memory block will appear in address
space 0-$3FFF (required by ResiDOS)
D5
RAM/ROM select: '0' = RAM is paged; '1' = ROM is paged. Only meaningful on the
original zx-badaloc clone, see notes
D4:D0 Bank
Select: one 16K bank out of 32 (512K) can be selected for paging by these 5
bits.
NOTE: As stated above, the FPGA version of the clone does not have any static ram nor rom chip. Every 16K bank comes from the DDR memory. Hence, this register controls the access to a 1MB memory space which can be paged-in, combining the original zx-badaloc 512K of RAM and 512K of ROM. In other words, the D5 bit is just one more bank select address bit (so 64 banks = 1MB can be accessed).
For compatibility reason,
however, these consideration might be taken into account:
When the clone
operates normally
(D6 = '0' = fastpage is not enabled) the DDR acts as the main memory for both 'ROM'
and 'RAM'. Up to 512K of 'ROM' can be accessed in the 0-$3FFF area by combining A18:A16 from $24DF
(nonstandard) register and A15, A14 from $1FFD and $7FFD registers respectively
(this allows 128K and +2 / +3 machines to run because rom selection works as on
the original hardware).
The HARD-CODED half of the 512K block of DDR will be the UPPER ONE, so if the user
wants to alter a ROM content on the fly by using the fastpage access, D5 should
be '1'.
The other 512K space (the lower half of the megabyte) is used as RAM memory. The first 128K will be mapped as in the 128K spectrum and can be accessed using the RAM Bank bits in the standard $7FFD register, while the remainder is for general purpose and can only be accessed through fastpage register. ResiDOS by Garry Lancaster uses fastpaging to access the entire 512K RAM area and requires D5 to be low. If the user wants to alter a memory bank which will reflect to RAM through fastpaging, the D5 bit should be '0'.
$64DF (25823): DDR MSB address bank (was "HI-RES on the original zx-badaloc)
Read / Write:
D7:D6
Not used
D5:D0 Upper memory address select: Up to 64
blocks (1 megabyte each) can be selected by this register.
This is an MSB extension of the FASTPAGE register. When fastpaging is enabled, these additional 6 bits provide access to the entire 64MB DDR space.
Memory Mapped Registers:
When D7:D4 in $1F register are equal to '1011' (Programmable Joystick Write Enable), 32 bytes of key-map data for the 16 joystick inputs can be written in memory at any 32 bytes boudary. Only A4:A0 are tested, so any memory write will also store data in the joystick registers. Hence, it is possible to write 'over' a ram array (to keep a copy of stored data) or write on a 'ROM' area, to avoid corrupting ram content.
Each joystick input has a pair of data bytes:
Byte 0
ZX-Spectrum keyboard eight COLUMNS (on Z80 Address lines): D7:D0 = A15:A8. A bit
SET means address column PRESSED
Byte 1 ZX-Spectrum
keyboard five ROWS, readable on $FE port: D4:D0 = D4:D0. A bit SET means key
PRESSED with the COLUMN byte
First pair of bytes stores keymap data for Joystick Input 1; second pair is for joy input 2 and so on.
It is imperative to perform joystick programming with interrupts disabled and in pure assembly, to avoid any undesired write operation which would certainly corrupt joystick setting.