Initilizing the internal ports of a Z180

416 views
Skip to first unread message

John Monahan

unread,
Mar 31, 2023, 7:21:39 PM3/31/23
to retro-comp
Just found this group!
I am trying to locate .Z80/Z180 code to initialize the internal ports in a Z180 CPU after power on. I'm building a S100 bus Z180 CPU board and would like to use/modify my own Z80 monitor.  Rather than dig/reinvent the wheel,  I'm hoping I can find somewhere that somebody has done the exact initialization code and published it.  I need to be able to use the Z180 serial port 0 at say 130K baud with a 18.4MHz Osc

Any help would be appreciated.


Mark T

unread,
Mar 31, 2023, 8:57:14 PM3/31/23
to retro-comp
Hi Monah,

Try looking at the RomWBW source.

Its probably not the same baud rate that you were looking for, but that should just need a few tweaks to the values.

Mark

Douglas Miller

unread,
Mar 31, 2023, 9:40:41 PM3/31/23
to retro-comp
One thing to be aware of, in case you didn't already pick this up, is that the Z180 internal I/O registers are addressed by 16-bit I/O port addresses, with the high 8-bits zero. The Z80 I/O instructions place the B register in those high 8-bits, but there are Z180 special instructions (out0, etc) that help with that. So, you either need to make sure both B and C have the right values (B=0), or use the Z180 special instructions. Also note that the Z180 internal I/O registers will default to 00-3F but can be mapped to other ranges to avoid conflict with external I/O ports, and that will need to be done at CPU init time - before you access the external I/O ports.

John Monahan

unread,
Mar 31, 2023, 11:12:29 PM3/31/23
to retro-comp
Thanks Mark. I have been looking up and down that GitHub site but cannot seem to actually find the Z80 Assembly code for thee CPU initialization. 
Thanks also Douglas I missed that point. What assembler do you use (or do you use DB's for OUT0 & IN0).

Douglas Miller

unread,
Mar 31, 2023, 11:27:59 PM3/31/23
to retro-comp
I use a macro assembler (zmac on Linux or RMAC/M80 on CP/M) and define macros for the Z180 instructions, but DB is the other way.

Wayne Warthen

unread,
Apr 1, 2023, 12:18:40 AM4/1/23
to retro-comp
Hi John,

I’m out of town for a few days with limited time.  I’m afraid that RomWBW is kind of complicated for your needs.  FWIW, the CPU initialization in in hbios.asm.  The serial port code is in asci.asm, but it includes dynamic baud rate management, so perhaps more than you want.  RomWBW uses TASM which supports Z180 opcodes if you use the right command line.

Thanks,

Wayne

Alan Cox

unread,
Apr 1, 2023, 6:41:09 AM4/1/23
to John Monahan, retro-comp
https://www.z80cpu.eu/mirrors/home.att.net/~halbower/

has Hal Bower and friends BPBIOS on it for various CP/M systems some
of them Z180. It should have all you need and more in clean tight
code.

Alan

John Monahan

unread,
Apr 1, 2023, 1:08:51 PM4/1/23
to retro-comp
Thanks Wayne, I'll await your return!
Alan where in that almost endless list of stuff are you referring to code to initialize Z180 internal ports etc.
John

Douglas Miller

unread,
Apr 1, 2023, 1:32:06 PM4/1/23
to retro-comp
I don't know if this will help, but I did this minimal Z180 ROM code here: https://github.com/durgadas311/minimalCPM/blob/master/rom/mincpm.asm

The "init" routine has most of it, but only initializes the core and ASCI ports. This is all written using Intel mnemonics, so you have that to deal with. If you find it helpful, I can answer questions.

This also shows a way of handling Z180 TRAPs, which will happen on executing an illegal instruction - which includes those pesky "undocumented" Z80 instructions.

John Monahan

unread,
Apr 1, 2023, 4:08:00 PM4/1/23
to retro-comp
That's absolutely fantastic Douglas -- exactly what I was looking for. Thanks.  I'm flying to NY on Monday - a good time to study what you have on the plane. I may have a few questions later in the week.

One quick question however right now.
Many S100 bus board ports reside in the 00-3FH range. In order to address them I was thinking of shifting the Z180 internal ports block to C0-FFH with:-
LD           A,0C0H         ;relocate I/O register to 0xC0
OUT0      (3FH),A

However the are some important S100 bus ports also in the C0-FFH range so I was thinking that to use them I would temporary  move the block back. Something like:-

LD          A,00H

OUT0     (FFH),A

Then say

IN0       E0H  (an S100 port in that range)

or

OUT0  E1H

Then return to the old setup

LD           A,C0H

OUT0     (3FH),A

Does the above sound OK to you?

John

Douglas Miller

unread,
Apr 1, 2023, 4:20:27 PM4/1/23
to retro-comp
I was pondering that same problem. I'm assuming that the other ranges are also in-use (40-7F and 80-BF)? I'm thinking that it might be more difficult than it sounds trying to temporarily switch back and forth, but have not really thought about it too much. One nice thing about the internal Z180 registers is that you can read them as well, so it is possible to save the current value and restore it - if that helps when dealing with interrupts or other unexpected diversions. My concern is whether you can always know exactly what I/O configuration is in use at a given time, and whether you can prevent interrupts while using an alternate config. TRAP and NMI might be the trickiest ones, since they cannot be masked/disabled.

On Saturday, April 1, 2023 at 3:08:00 PM UTC-5 monah...@gmail.com wrote:
...
One quick question however right now.
Many S100 bus board ports reside in the 00-3FH range. In order to address them I was thinking of shifting the Z180 internal ports block to C0-FFH with:-
LD           A,0C0H         ;relocate I/O register to 0xC0
OUT0      (3FH),A

However the are some important S100 bus ports also in the C0-FFH range so I was thinking that to use them I would temporary  move the block back. Something like:-
...

Wayne Warthen

unread,
Apr 1, 2023, 6:13:20 PM4/1/23
to retro-comp
I’m not 100% sure about this, but I think that when you write to an internal Z180 port, the write is still pushed out on the bus and will be seen by peripherals that share the same port addresses at the time of the write.

-Wayne

Douglas Miller

unread,
Apr 1, 2023, 6:31:19 PM4/1/23
to retro-comp
Found this in a 1988 Z180 document:
z180-io.png
Which makes me think there could be problems if any internal I/O access matches anything external. Caveat emptor.

Steve Cousins

unread,
Apr 1, 2023, 6:51:31 PM4/1/23
to retro-comp
The SCM and accompanying CP/M BIOS source code is part of the download here:
https://smallcomputercentral.com/small-computer-workshop/

You will find the SCM BIOS code in the folder and files:
SCWorkshop\SCMonitor\Source\BIOS
SCWorkshop\SCMonitor\Source\BIOS\SCZ180\Z180Support.asm
SCWorkshop\SCMonitor\Source\BIOS\Framework\Devices\ASCI.asm

The CP/M BIOS Z180 code is here:
SCWorkshop\SCMonitor\Apps\CPM_CBIOS_and_PutSysPlus\Includes\ConsoleDevice-ASCI.asm

John Monahan

unread,
Apr 2, 2023, 12:35:26 AM4/2/23
to retro-comp
Wayne/Douglas that is actually a problem, one normally does not want writes to a Z180 internal port "spilling over" on to a S100 bus port.  Fortunately most important S100 bis ports are not in the C0-FFH range.  One however would have to look carefully at all internal Z180 port writes. Perhaps I should put in a hardware circuit to temporary block S100 bus port writes with a special S100 bus write to a port outside the C0-FFH range. Once the circuit is activated all S100 bus port writes are temporary blocked.

Andrew Lynch

unread,
Apr 2, 2023, 5:24:43 AM4/2/23
to retro-comp, John Monahan
Hi John
I see you posted on retro-comp already and someone replied with check out the RomWBW source code.  That's the definite "go to" authority for small hobbyist Z180 type projects.  I use it for all of mine.

Thanks, Andrew Lynch

--
You received this message because you are subscribed to the Google Groups "retro-comp" group.
To unsubscribe from this group and stop receiving emails from it, send an email to retro-comp+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/retro-comp/9d864cba-d325-4dcb-9aff-c9079b317880n%40googlegroups.com.
Message has been deleted

Alan Cox

unread,
Apr 2, 2023, 6:10:04 PM4/2/23
to retro-comp
On Sat, 1 Apr 2023 at 23:13, Wayne Warthen <wwar...@gmail.com> wrote:
>
> I’m not 100% sure about this, but I think that when you write to an internal Z180 port, the write is still pushed out on the bus and will be seen by peripherals that share the same port addresses at the time of the write.

Yes - although you can add a bit of external logic so that IORQ is
kept high if A6/A7/A8 are all high then put the Z180 stuff at C0-FF.
It does mean you have to use (c) forms to access the external stuff at
C0-FF as 1CF0-1FF or similar.

John Monahan

unread,
Apr 2, 2023, 9:08:41 PM4/2/23
to retro-comp
Or I assume use "out0"

Douglas Miller

unread,
Apr 2, 2023, 9:14:19 PM4/2/23
to retro-comp
There's a lot you can do if you're designing the entire system from scratch, but when you have to co-exist with existing I/O boards, such as in an S-100 system, you are bound by the hardware and software (if the hardware and software does not allow port re-configuring). If the existing hardware/software you want be compatible with does not leave one of those ranges available, you'll need to get creative (or restrict the hardware configurations, or have multiple versions for different configurations).

Alan Cox

unread,
Apr 2, 2023, 10:15:21 PM4/2/23
to retro-comp
On Mon, 3 Apr 2023 at 02:08, John Monahan <monah...@gmail.com> wrote:
>
> Or I assume use "out0"

An out0 will generate the external bus cycle as well so unfortunately
you can't just move the Z180 I/O space up and down to dodge whichever
port you need to use because your writes will also be seen by external
devices.

When you need to access all the space in a legacy system and co-exist
(eg as a plugin CPU upgrade) then you add logic so that IORQ only goes
low for the 3/4 of the I/O space that is not being used by the Z180 or
for the other quarter if another address line is high.

So if you used C0-FF you'd keep IORQ high if you saw A7=1 A6=1 A8=0

This then allows you normal access to the other 3 quadrants of the I/O
space and also allows you to access the remaining 1/4 with the
slightly more cumbersome ld bc,#0x01XX out(c),a sequence.

Douglas Miller

unread,
Apr 3, 2023, 7:53:37 AM4/3/23
to retro-comp
However, the external I/O cycles only matter if there is external hardware at those specific ports (registers). It is possible to dance around depending on which internal ports you are accessing such that you don't touch any external hardware. Not pretty, and not something I'd like to do, but possible - depending on the external I/O map. However, an extremely unlucky external I/O map might result in certain internal ports that cannot be safely reached using any range.

If I understand John's dilemma, none of the 4 possible I/O ranges is suitable all the time. It's not clear to me if that is the case for his particular configuration or that it will be needed to support a wider range of hardware configurations.

Also note that the z180 does not provide any external signals that tell you which internal I/O range is currently selected, so you have to do something to mirror that register externally so you can use it to suppress IORQ. This external mirror register (decoding) has to also move around with the I/O range, so it's not a simple thing to implement.

On Sunday, April 2, 2023 at 9:15:21 PM UTC-5 Alan Cox wrote:
...

An out0 will generate the external bus cycle as well so unfortunately
you can't just move the Z180 I/O space up and down to dodge whichever
port you need to use because your writes will also be seen by external
devices.
...

Alan Cox

unread,
Apr 3, 2023, 9:33:37 AM4/3/23
to Douglas Miller, retro-comp
> Also note that the z180 does not provide any external signals that tell you which internal I/O range is currently selected, so you have to do something to mirror that register externally so you can use it to suppress IORQ. This external mirror register (decoding) has to also move around with the I/O range, so it's not a simple thing to implement.

From a practical perspective though you either build a tiny bit of
logic that knows where the internal I/O will be placed, or you just
use an internally controlled signal (it has to be internal - eg RTS or
something) and or it with IORQ. One gate of a 74HCT32 but a tiny bit
of software complexity as you have to turn on external I/O use the reg
and turn it back. Much like a Z280.

And sometimes like the XLR8R card on the TRS80 you are just lucky with
the native I/O assignments.

Alan

Douglas Miller

unread,
Apr 3, 2023, 2:58:34 PM4/3/23
to retro-comp
You would have to find an external signal that can be altered without I/O instructions, or that uses an I/O port address that is not impacted by the problem (never has an external port conflict no matter what I/O range is selected).

On Monday, April 3, 2023 at 8:33:37 AM UTC-5 Alan Cox wrote:
...

From a practical perspective though you either build a tiny bit of
logic that knows where the internal I/O will be placed, or you just
use an internally controlled signal (it has to be internal - eg RTS or
something) and or it with IORQ. One gate of a 74HCT32 but a tiny bit
of software complexity as you have to turn on external I/O use the reg
and turn it back. Much like a Z280.
...

Alan
Reply all
Reply to author
Forward
0 new messages