Source:
www.vintage-computer.com
Hi,
Is anyone interested in a home brew Z80 computer project? I have built them in the past and
are a lot of fun to do. There are some others on this forum who have built their own machines
but I am curious to see if there are others who would be interested in a group project. Please
reply here or PM me if interested.
My latest Z80 machine is an updated design that tries to keep it simple while retaining the
"feel" of vintage machines. It is a blend of technologies to address some of the major
frustrating things which I faced as a home brew builder.
The first issue is parts availability; if you can't get the parts you can't build the machine. For
this project, I am selecting only rather common and readily available 74LSxxx chips and LSI
components like Z80 CPU, 16550 UART, 8255 PPI. All parts are readily available from vendors
such as Jameco.com, etc. Custom programmable devices (except for boot EPROM) such as
GALs, PALs, FPGAs, etc are out as those devices are difficult for many hobbyists to get
without the special tools required to program them.
The second issue is the technology needed to build the unit; many of the advanced PCB
techniques require special tools and processes which are beyond the typical hobbyist. As a
result, I selected plain "through hole" (i.e. generic DIP packaging with 0.10" pin spacing)
technology which is fairly simple and only requires a 25 watt soldering iron and related tools
to produce. Any of the various SMT techniques are out even though they are much more
dense they are too difficult.
The third issue is the PCB itself; there are a variety of techniques to make your home brew
computer on such as breadboarding, wire wrap, and point to point protoboards. I have used
those techniques and they do work fine although I think they tend to be for "one off" and
temporary projects. The tend to devolve into a "rats nest" over time or develop other issues
with reliability. For this project, I am going to try the custom manufactured PCB approach.
Although initially more expensive, it promises to make for a much more reliable product and
tremendously reduce the work necessary to build the device. In addition, with recent
developments in free software tools and low cost PCB manufacturing, the cost associated with
this approach has come down dramatically.
Finally, there has to be software for the machine. My goal for this project is standard CP/M
2.2 booted from a ROM drive and using a RAM drive for storage. This is doable since I have a
custom CP/M build with CBIOS for my previous Z80 home brew project. This machine would
be similar to the existing design and require some changes to the code. Most generic CP/M
applications should run unmodified. As with any CP/M platform, some hardware specific
programs are required such as debugger, format utility, RTC application, etc.
Andrew Lynch
Hello Andrew,
Thank you so much for all the detailed descriptions. The above paragraph is the
core of your present design, and it would be very helpful if you would kindly
explain what goes on when you turn the circuit on. If you could provide a flowchart
or something, it would be even more educational.
Thank you very much
ziloo
Hi,
Well, I can try to explain. Basically when the CPU is reset there are two MPCLs. One is
attached to an EPROM and the other to a SRAM. The default memory configuration (ie, MPCL
74LS273 latches are both set to $00) there is a 32K ROM page at $0000 to $7FFF and a fixed
32K RAM page at $8000 to $FFFF. The upper RAM page is fixed and can never be changed.
-1-
However the lower ROM page can be switch into any of 32 different ROM pages (1MB) or
switched out entirely and replaced with one of 16 different RAM pages (512K).
When the CPU boots, it starts executing at $0000 as per every Z80. The first thing it does is
"toss" the program it is running (aptly named "loader") into upper memory and transfers
control to the newly installed "RAM monitor" running at $F800-$FFFF. The RAM monitor
continues with the rest of the hardware initialization which includes switching out the lower
ROM page and creating a full 64K of RAM. The RAM monitor gives several monitor like
functions you'd expect like "display" "load Intel hex format" "go" "fill" "substitute" and the
like. The last command it has is the "c" command which is basically a CP/M boot loader. Press
c and almost immediately a CP/M prompt appears with A: being a RO ROM drive (32K soon to
be 996K) and B: RW RAM drive (448K).
The first 32K of the ROM is sneakily formatted as a 32K CP/M disk complete with boot tracks
(where loader and dbgmon are stored). I forget the exact format right now but the ROM is
divided up into 128 byte sectors, tracks of some size, and the whole thing is 32K long. When
CP/M is running it mounts A: as the block device in the CBIOS and you can do all the normal
disk functions except write. You can get a directory of the three programs I placed into the
ROM image. If I recall correctly, they are gm (go monitor), RTC (real time clock) and XM
(XMODEM). There are supposed to be a bunch more but since I have to hand code the
directory entries into the ROM image I have only done those few programs.
Hopefully this helps explain how the TP boots. Maybe you could ask a more specific question
if there is something else you'd like to know? This is intended to be a open and public project
so the details are all out in the open. I will be posting the software on the website once I have
some confidence it more or less works.
BTW all the software is assembled from source, including CP/M 2.2 using TASM301. It is a
free (as in beer not as in speech) DOS based assembler. In keeping with the open and public
and free themes I'd like to convert to development environment similar licensed to KiCad for
the hardware assembly but just haven't gotten that far yet. Similarly I would like to transition
to a free OS like ZCPR or whatever it is called. Somebody still retains the rights to CP/M but
have made it available for usage.
When you say RAM monitor I assume you mean a monitor in ROM that uses RAM,
or?
Are images (or, even better, sources) for these ROMs available anywhere?
Instructions for the monitor?
Hi Mike,
The RAM monitor is one that runs entirely in RAM, starting at $F800. It is stored in ROM and
loaded into the high page as part of the boot process. Once the RAM monitor starts, it
initializes the hardware and switches out the ROM page. Its actually called "dbgmon-e" but I
call it the RAM monitor to distinguish it from the ROM monitor which used to run entirely in
ROM. It is a similar monitor of an earlier generation.
The ROM images are available on my workbench. :-) I will be publishing the sources of the
assembler on the website along with links to the tools I am using. Basically you don't need the
ROM images if you have access to a DOS PC since TASM301 generates the necessary binary
image (ROMIMAGE.BIN) from the assembler sources.
What is the address range for this newly established 64k RAM?
Hi! Excellent questions!
After the boot process is completed (ie, the RAM monitor is running) there is RAM at $0000 to
$7FFF and at $8000 to $FFFF. CP/M theoretically has access to a full 64K of RAM, however,
the TPA is somewhat less than that since it shares the RAM with CP/M itself and 2K for the
RAM monitor.
-2-
What address range the CP/M is residing on?
CP/M loads at $D400 and uses up to $F2FF. CP/M is composed of three parts, the CCP, BDOS,
and CBIOS. The CBIOS I wrote starts at the somewhere near the end but I don't remember
the exact location. It is in the source. I seem to recall the TPA is 56K(?) or so. I don't
remember the exact number but it is in the CP/M 2.2 source included.
How are these ROM and RAM units addressed? Z80 can only address 64K of
memory and
how is the bank switching implemented? (Do I understand it correctly?)
The regular $0000-$FFFF memory map is accessed normally. The extended RAM and ROM
are accessed by switching in the lower 32K memory page by writing to the various MPCLs.
They appear as write only IO ports. I think they are $78 for the RAM MPCL and $7C for the
ROM MPCL. Since they initialize to $00 upon reset, writing 1s to any of the latch bits cause
address lines to be set high. The RAM MPCL has extended address lines (A15, A16, A17, A18)
and the ROM MPCL has extended address lines (A15, A16, A17, A18, A19). The ROM MPCL
also has a ROM_ENABLE line at bit 7. Note the address lines are local to the specific MPCL
and its memory device. The CPU can only indirectly access the extended memory address
lines via its MPCL.
All the hardware information is contained in the schematic and PCB layout on the N8VEM
website. Soon I will be publishing a ZIP file of all the software and make files. It is all pretty
crude stuff and DOS based for easy usage. It all probably needs a serious rewrite but the
intent is/was to just show viable operation of the concept.
One curious artifact of the original design is that the RAM chip has its highest 32K page
"pinned" to A15 by a 74LS32. Whenever the CPU sets the A15 high, all the SRAMs extended
address lines (A15, A16, A17, A18) are forced high. That way there is a "permanent" 32K RAM
memory reference for running programs which manipulate the memory map. The original
design did not have this and I discovered the hard way that if you are going to change the
memory map, the CPU needs a source of permanent context for reference. Otherwise context
gets lost and the CPU goes into LA-LA-LAND.
...The first 32K of the ROM is sneakily formatted as a 32K CP/M disk complete
with boot tracks (where loader and dbgmon are stored). I forget the exact format
right now but the ROM is divided up into 128 byte sectors, tracks of some size, and
the whole thing is 32K long...
Would you please explain more details about addressing the sectors and tracks?
How are the information stored on these tracks/sectors: as linked lists, some kind
of an allocation table...etc?
OK, well really the real tracks and sector information is contained in the CBIOS design. It
views the data contained in the ROM as a 32K block device "disk". The CBIOS has an
algorithm which when you tell it load track 00, sector 00, it knows to go get the first 128
bytes of the ROM. Depending on what track/sector combination you request, it returns
different 128 ROM memory regions as a sector. It really is a kind of neat trick.
The ROM itself does not contain any disk meta-data like sector/track information like you'd
find if you used a Catweasel to do a raw read of a soft sector floppy disk. It is more like a dataonly
disk image where the disk imaging program knows which data goes with which
track/sector based on the data's relative position within the image file.
The ROM is formatted in such a way that the CBIOS can parse it out using its track/sector
block device read (and write in the case of the RAM drive). You can literally see the 32K disk
structure in the layout of the ROM. It follows the CP/M DPB values in the CBIOS.
-3-
I think goes something like this...
each track is 4K long and is composed of 32 sectors each 128 bytes in length. Within the 32K
ROM there are 8 tracks. Track 0 and 1 are reserved as "system" tracks to contain the loader,
dbgmon, & CPM boot image. Starting on track 2 is the directory structure which is like four
sectors long or something. Actual disk data starts someplace after the end of the directory
and goes to the end of the 32K ROM.
There is a similar concept for the RAM disk but with a different set of DPB values. Eventually
I will convert the 1M ROM into a format similar to the RAM drive and include an entire CP/M
set of utilities and some development tools, applications and the like. Of course this is user
customizable so anything can go in there but right now you have to format the ROM image by
hand which is a real PITA.
One of the things I put on the "help needed" section of the N8VEM website is for some
programming whiz to make a DOS program which given a set of files and a DPB, will create a
formatted ROM image. The program would not be that hard to write (I think) but would
require some fairly detailed knowledge of how CP/M disk layout and formatting. I am doing
that by hand now but it would be highly useful for others to have a utility which could do this
automatically. All the necessary technical information is available online in the CP/M
documentation and I can help point out where if anyone is interested.
CP/M loads at $D400 and uses up to $F2FF.
This is about 8k of program code; where is the rest of CP/M?
The CP/M EPROM actually contains many programs such as a loader,
the RAM monitor, the CP/M image, XMODEM, and RTC utilities....
...You can transfer programs into the RAM drive by XMODEM (included in the
ROM drive)
great? Well, I wouldn't go that far... Wait until you see the source code ;-) I am sure you'll
come up with some other adjectives.
Yes, I seem to recall the TPA is 53K in length for some reason. 2K is used for the RAM BIOS.
CCP and BDOS uses 5.5K, if I recall correctly. I think the CBIOS and disk buffers use up the
remainder. The CBIOS supports an IDE interface as well which chews up quite a bit of RAM
and also requires a 512 byte deblocking buffer someplace up in high RAM.
The IDE interface is on the Test Prototype machine I built last year. The IDE portion works
great. It could easily be converted to a CF drive with an adapter, I think. I used a small 1.2GB
IDE hard disk but it really only used like three 8MB partitions.
Later I built a floppy disk interface onto the card but it had issues with grounding and I ran
out of time to work on it. It was completed but I never got a chance to test the software for it
even though it was largely already written. I still have all the schematics and intend to
incorporate them into the disk IO board later on. I will probably have to design out an
obsolete part (SMC FDC9229 data separator) that has become unobtainium and replace it
with a SMC FDC9216 or UM8326. That is an other story for a different day though.
I think I bought a broken NorthStar Horizon about then and became obsessed with fixing it
and ended up putting the home brew computer "on hold" until that passed. I fixed the Horizon
and it is a great machine but now I am finally ready to return to finish this home brew
computer.
One of the reasons I transferred the design to manufactured PCBs is to fix the root problem of
the grounding on the Test Prototype. Since it used prototype boards with point to point
wiring, after a few generations, it began to resemble a ball of wire that you could occasionally
glimpse a component in. It was rather difficult to work on. The new PCBs are MUCH nicer to
assemble!
-4-
1- Is "loader" part of ROM monitor or a separate program.
From a source perspective, the loader is its own program. As a binary, it is combined into the
same ROMIMAGE.BIN as the RAM monitor and the CPM boot image. The latter two programs
are just data fields loader transfers to their appropriate places in memory. Loaders last job
task is to jump to the cold-start vector on the RAM monitor, who in turn swaps out the ROM
and loader disappears from the CPU address space entirely. You can boot CP/M from the RAM
monitor if desired. Or not. Frankly, I find the RAM monitor just as useful as CP/M is for the
most part. I split my time between the two.
2- Are both ROM monitor and CP/M on the same EPROM?
Yes, the RAM monitor and CP/M boot image are in the ROMIMAGE.BIN stored in the first 8K
of the 32K ROM page. The CP/M boot image is only the CCP+BDOS+CBIOS. The rest of the
CP/M transient utilities are stored on one of the IDE hard disk partitions. My plan is to move
them and some other stuff onto the ROM drive once it expands from 32K to 992K.
3- Is ROM drive the same as CP/M EPROM?
Yes. The ROM drive (A:) is just like a floppy disk. It currently is the first 32K of the EPROM --
which used to be a 32Kx8 28C256 EEPROM but is now a 1Mx8 27C080 or 128Kx8 27C1001
EPROM. The first two tracks are reserved for system tracks which contains the loader, RAM
monitor, and CP/M boot image. The remaining 6 tracks (24K) are reserved for programs like
GM.COM, RTC.COM, and XM.COM.
I'll post the files tonight in the ZIP file and when you inspect the make files and the resulting
ROMIMAGE.BIN, it will be more apparent how the system is structured. It really is pretty
simple structure but neat how it all works out.
What does "rehosted" mean?
"rehosted" means I modified the source code so that the "new" versions run on the new
hardware and reflects the updated designs. Basically two main software components had to
be changed to reflect the new design has RAM and ROM MPCLs compared to the previous
generation which had only a single MPCL. The RAM monitor hardware initialization routine
and the CP/M CBIOS had to be modified. I haven't located any other necessary changes
although it would not surprise me if there were some others lurking someplace.
...requires a 512 byte deblocking buffer someplace up in high RAM.
The first time I read about "blocking and deblocking", I thought blocking means to
stop/prevent!!! I don't know whether this terminology was coined by Gary Kildall
or it was someone else's idea. As I understand, blocking means "arranging blocks
of data" and deblocking means "removing blocks of data" (or was I right the first
time?!?!).
Would you please give a more detailed explanation as to was goes on in that
buffer...
Yes, "deblocking" in the context of a CP/M CBIOS is an algorithm that converts whatever disk
format sector size to the one that CP/M expects to use, namely 8" floppy disk with 128 byte
sectors. When the CBIOS "deblocks" what it does is take the minimum sector size block from
the native device, say an IDE hard disk minimum which its sector size is 512 bytes, and
-5-
converts it into one to four 128 byte sectors usable by CP/M natively.
The CBIOS I wrote implements a crude deblocker for the IDE interface. Basically it is just one
for one mapper and it horrifically inefficient. However, it does work reliably as far I could tell
and the IDE harddisk is way faster than the Z80 can handle anyway. The more sophisticated
CP/M deblocking algorithms were able to deblock and retain the sector information in a sort
of tiny disk RAM cache for subsequent reads.
1- I see a mixture of ASM programs in both 8080 and Z80 instruction sets in your
ZIP file. Would you please explain about this?
2- I have heard so much about IOBYTE in CP/M; would you please give an
explanation about what it is all about...
Uhhh. Yeah. Not one of my proudest moments, that's for sure. :-)
Actually, it is an artifact of trying to convert the entire code base to allow compiling on the
Test Prototype target itself using the standard CP/M toolset (ASM). I tried to restrict myself to
just the 8080 mnemonics but occasionally a Z80 op code was necessary for some reason or
other. In those cases, I basically forced the assembler to put in the proper op code even if it
didn't recognize the mnemonic. The exact technique is one I learned from Allison. For
example:
LDIR1: .DB $ED,$B0 ; Z80 "LDIR" INSTRUCTION (REMOVE)
Of course, there is no 8080 equivalent to LDIR and I needed it for some block transfers in
loader-a and the CBIOS. I suppose I should just convert it all back to Z80 and just accept the
Z80 as a requirement but "true" CP/M portable applications are written using only the 8080
instructions. There are a few exceptions to the rule.
My goal was to remove all the Z80 peculiar instructions and have "pure" 8080 only
instructions but that got to be increasingly difficult and when other problems developed, I
pushed the project to the back burner. There are 8080 only equivalent subroutines and
macros to help Z80 -> 8080 conversion and some of those are in the source, I think.
Some files in the ZIP file are all Z80 mnemonic and others are 8080. You can tell which is
which by reading the buildTP2.bat file and which TASM commands require -85 (for intel 8085)
and those for -80 (for zilog Z80).
My hope for publicly posting the Test Prototype project online, warts and all, is to keep the
information from being lost entirely. It is possible that when/if people start making these SBCs
for themselves that some of this code will get better testing and maybe even cleaned up a bit.
Certainly there are many hours of work needed
Regarding the IOBYTE; in essence that is a tool where the CP/M CBIOS allows some IO
abstraction and redirection. The IOBYTE allows switching between CP/M devices such as
CON:, PUN:, LST:, PRN:, etc with minimumal impact to the CBIOS. The Andrew Laird
"Programmer's Guide to CP/M" does a great job explaining what and how this works. It was
my intention to support IOBYTE in the CBIOS but again, it got sidetracked. My CBIOS does
not support IOBYTE in its present form.
You'll find there are a great many rabbit trails to follow in the source code. Some actually go
someplace and others just trail off into the weeds. Like I said, the test prototype software
surely isn't the prettiest thing you'll ever read but it more or less works.
You remembered to have your aspirin and glass of water ready before you started reading it,
right? :-)
PS, Check out the silliness in the dbgmon-e source. It was originally for an SBC-200 and
"adapted" for new use on the Test Prototype. It is rather ghastly and even includes boot code
for FDC1793 disk controller. The only problem with that is the actual disk IO board uses the
NEC765 FDC. :-)
Originally, I was going to use a WD2797 FDC chip but later changed my mind. I even have a
-6-
WD2797 still sitting here just waiting for a PCB to put it in.
Do I understand correctly then that:
1- TASM takes the 8080/8085 code and assembles it into a form that is executable
on a Z80 CPU?
2- Probably most vintage computers with Z80 CPU were using CP/M versions
written entirely for 8080 CPU?
Yes, TASM is a Table Assembler and is able to cross assemble for many targets including
8080, 8085, and Z80. Not that TASM can translate assembler mnemonics between CPUs
though but the Z80 and 8085 have backwards compatible opcodes with the 8080 so it sort of
appears like it.
The Zilog Z80 is opcode compatible with 8080. Zilog published a new set of assembler
mnemonics for Z80 very different than the Intel 8080 mnemonics but the resulting machine
language is a backwards compatible superset of the Intel 8080 opcodes.
The confusion arises because Zilog came up with a new mnemonic format which was
improved over the much older Intel mnemonic format. A lot of assemblers support one or the
other and sometimes both. TASM supports both Intel and Zilog mnemonics and has rather
conveniently facilitates my bad habit of switching randomly between the formats.
The Intel 8085 is essentially the same as the 8080 except for a couple of new instructions (not
supported on Z80) and uses identical mnemonics.
CP/M was originally written on an 8080 and all the documentation are Intel 8080 specific. I
believe all the CP/M tools are in Intel mnemonic format as well. The 8085 and Z80 both run
8080 opcodes and are both far more common CPUs. As a result most CP/M machines are not
8080 but use the Z80or 8085 instead. I am pretty sure the majority of CP/M computers are
Z80 though.
There are some CP/M applications which use Z80 specific opcodes like Borland Turbo Pascal
but they are very few. I cannot think of another example of Z80 dependent CP/M code except
for possibly some CBIOS versions.
Here is great site to sort through the wreckage of old CBIOSs. I have gotten some really great
ideas sifting through these:
http://www.speakeasy.org/~rzh/bb.html
Actually there are not all that many 8080 machines left due to their early technology and
unusual voltage requirements. The Z80 machines are far more common. Intel 8085 is also
very popular but more so in industrial embedded applications than in microcomputer because
the chip set is specially designed for easy integration and low part count. You can run CP/M
on 8085's but they are a less common than Z80 regarding microcomputers.
If you are considering designing your own SBC you should consider using the 8085 as the
CPU since it is possible to make very low chip count machines with them. I hope this helps
explain things. Feel free to ask if there is anything I can better explain.
.. CP/M loads at $D400 and uses up to $F2FF...
... I seem to recall the TPA is 53K in length for some reason. 2K is used for the
RAM BIOS.
CCP and BDOS uses 5.5K, if I recall correctly. I think the CBIOS and disk buffers
use up the remainder. The CBIOS supports an IDE interface as well which chews
up quite a bit of RAM and also requires a 512 byte deblocking buffer someplace up
in high RAM...
-7-
1- Is CBIOS included in the $D400-$F2FF address interval?
1- How much memory is available for an application program?
2- Is there any unported portion of CP/M still left in the EPROM?
Yes, the CP/M boot image includes CCP+BDOS+CBIOS. The loader copies a memory image
range of $1EFF in length (a little bit less than 8K) although the actual length of the CP/M
binary boot image is somewhat less than that. CCP+BDOS are 5.5K and the remainder is the
CBIOS.
1- How much memory is available for an application program?
I am not certain but I think it is 53K. After a quick review of the CPM22-d.asm code, I believe
transient program area (TPA) = (MEM -7) * 1K where MEM = 60 in this case. For the most
part, that is sufficient. I have found CP/M TPA 48K or greater to be pretty usable.
In theory, I could boost MEM to 62 but it'd cost the RAM monitor and since I use both about
the same amount, I'd rather keep it. Also the CBIOS could probably be rewritten to be lot
tighter code which would shrink it some too. However, more likely is that the CBIOS will grow
not shrink since I do intend to add support for an FDC eventually which will further shrink the
TPA probably another 1K or so.
Now this design is largely out in the public, there is nothing stopping anyone from creating
their own ROM images and custom CBIOSs. In fact, I rather encourage it. I will speak with my
friend to see if he can add support for the N8VEM hardware into a simulator. It should be
fairly easy as there are only 5 simple IO devices.
2- Is there any unported portion of CP/M still left in the EPROM?
No, it is all converted as best I can tell. The rest of CP/M ia/are transient programs which are
identical for all CP/M distributions. Those include STAT, ASM, DUMP, PIP, LOAD, etc. Those
are currently stored on an IDE HD partition which I haven't attached yet but will be in the not
too distant future. However, if anyone wants to use them now, they can boot the computer,
start CP/M and use XMODEM to transfer the files to the RAM drive where they'll reside as
long as power is applied.
1- Please explain in more details about communication between N8VEM board ;)
and something like Hyperterminal.
Yes, I use Hyperterminal to communicate with the SBC over the serial port. There is a custom
serial cable required and I suppose I need to publish the plans for it as well. I'll do that. Funny
you should ask about Hyperterminal though as I have been working on the serial connection.
Up until today, the SBC used 3 wire serial connection with no flow control at all. That is really
not my preferred approach but I never could figure out how to make hardware flow control
work properly.
So this morning I got out the RS-232 serial break out box and the pin outs for the PC serial
port and the 16C550 datasheet. I think I have fixed the problem so now the SBC appears to be
using hardware flow control. Still, I need to verify it is working. The custom serial cable is
pretty easy to make and when I confirm it is working I will post how to make it.
2- Can you download a file from a PC to N8VEM board?
Yes, you can use XMODEM to send and receive files from the SBC.
-8-
3- If so, which software is responsible for communication: Ram Monitor or
Xmodem?
You can use either to transfer a file from a PC to the SBC. Using XMODEM is probably easier
or you can use the Intel Hex transfer utility in the RAM monitor. To send a file from the SBC
to the PC just use the XMODEM or text capture.
1-Upon starting the SBC, under which supervisory program does the N8VEM
board eventually end up...the Monitor or CP/M?
After pressing the RESET button and waiting a few seconds, the SBC comes up in the RAM
monitor mode. You can boot into CP/M by pressing the "c" key and waiting another few
seconds. It is not instantaneous because the initialization routines clear all the RAM to a
known state and format the RAM drive which takes a few seconds. It is quiet though...
2- How do you transfer operation from one to the other?
From the RAM monitor to CP/M, press "c" to boot CP/M
From CP/M to the RAM monitor, type the "gm" command for "go monitor".
You can switch in between the two quite easily.
3- Xmodem is a whole separate program, and CP/M is not aware of its presence;
because Xmodem is the communicating program for CP/M, it could not be called in
by CP/M like some other utility programs on the HD/FD/RamDrive. So it is kind of
a CBIOS extension...Do I understand this correctly?
Well ... not quite. XMODEM is a CP/M program in its own right although it does have its own
unique CONIN, CONST, and CONOUT routines instead of using the ones provided by the
BDOS or CBIOS.
You call up the XMODEM program by typing "xm" at the CP/M prompt. It is just like any other
CP/M program for the most part. It uses BDOS routines for its file access for instance. The
RTC also uses some BDOS routines. I suppose they could be stand alone programs but why
rewrite all those file IO routines when CP/M provides them so nicely?
According to buildTP2.bat file:
Xmodem is assembled and linked to CP/M and few other programs to create a
binary file to be downloaded as Rom image.
Was it possible that Xmodem could have been treated like any transient program
that could be loaded by CP/M into Ram, but for now it is manually linked to the CP/
M program. If so, then the "XM" command has been manually added to CP/M (in
the absence of an storage device for Xmodem program)?
Oh, I think I see the misconception here... XMODEM is not linked to the CP/M boot image. It
is a transient program like RTC and GM or any other CP/M transient program. XM is in the
same ROMIMAGE binary because the ROMIMAGE is basically just like a miniature disk
image. They are together like various programs would be on a regular disk but XM is not
linked to CP/M. It is written in pure assembler and only called into RAM when the CCP
requests it. It does use BDOS calls but so does almost every CP/M program.
You'll notice that the loader, dbgmon, and CPM boot image are all on the first five 2K system
tracks which are $0000 - $27FF (10K) in the ROMIMAGE. The CP/M directory sectors are at
-9-
$2800-$2BFF (1K) and the programs themselves are stored in the data sectors $2C00-$7FFF
(21K).
I have been testing XMODEM as part of my attempts to get a documented serial cable. I think
I have a working prototype cable that works with hardware handshaking. One thing I have
noticed is that the new PCB seems a lot more solid and reliable than the previous prototype
board version. It used to be that XM was rather flaky but now it seems rock solid. I can load
XM in to RAM, run it, pull data files from the PC and back again without the slightest hiccup
or even a retry. That is quite different than before. I've been doing the transfers with large ZIP
files as they are easy to detect if there is file corruption being introduced.
Thanks and let me know if this helps explain how this all works. Just try to think of
ROMIMAGE.BIN as a miniature disk image, not an executable. Really the only thing in
ROMIMAGE.BIN which actually executes in place is the loader. Everything else is just so
much data -- just like on a floppy disk. Not until the OS pulls the data into RAM does it
become real executables.
...the programs themselves are stored in the data sectors $2C00-$7FF...
Now, what is the use for the higher EPROM address range, namely $8000-$FFFF?
You can get a directory of the three programs I placed into the ROM image. If I
recall correctly, they are gm (go monitor), RTC (real time clock) and XM
(XMODEM). There are
supposed to be a bunch more but since I have to hand code the directory entries
into
the ROM image I have only done those few programs.
Would you please explain about "hand coding"...
Now, what is the use for the higher EPROM address range, namely $8000-$FFFF?
In its current implementation, the ROM drive is only a single 32K page so there is nothing in
outside the first page (ROM page 0, $0000-$7FFF). It is an artifact from the original design
that used a 28C256 EEPROM (32K). However when I get the CBIOS updated with the new
design, the ROM drive will have 32 32K pages for 1MB total capacity from the 27C080
EPROM.
From a CPU perspective, the ROM only appears as $0000-$7FFF in its lower memory page
window. The ROM never appears in $8000 or above. The MPCL set the upper address lines so
that you can see one of the 32 32K "windows" into the ROMs address space.
Would you please explain about "hand coding"...
Yes, the "hand coding" is literally typing in the characters for directory entries manually. If
you'll look in the ROMFRMT.ASM file you'll see the data entries of the three CP/M transient
programs. Making manual entries is pretty labor intensive compared to just letting CP/M
BDOS do it automatically for you. If you want to add a program, ROMFRMT.ASM has to be
updated as well where ever the data image would reside in the ROMIMAGE.BIN.
I have really enjoyed our "Socrates dialogs" ... :argue:
You might have noticed that this thread has had hundreds of readers over the past
few days, so there must be great interest in learning about SBCs running CP/M.
Now, why not getting into more details:
... the "hand coding" is literally typing in the characters for directory entries
manually. If you'll look in the ROMFRMT.ASM file you'll see the data entries of the
-10-
three CP/M transient programs...
org $2800
.db $00,"GM COM",$00,$00,$00,$01
.db $01,$00,$00,$00,$00,$00,$00,$00
.db $00,$00,$00,$00,$00,$00,$00,$00
.db $00,"RTC COM"...
Would you please go over the entries and explain what they are all
about...:winking:
Hi! Sure, no problem. I am glad you enjoy it and I look forward to helping you and others as
much as I can. All I did with the ROMFRMT.ASM program is what BDOS normally does when
it creates a file in the block device. Each file has a 32 byte entry with various pieces of
metadata such as user, filename, the number of records, number of extents, where the file is
on the disk, etc. CP/M has a very straight forward file system so doing this is much easier
than it may sound. Here is a link with a good explanation although there are more detailed
explanations in the CP/M documentation. I think the CP/M Alteration Guide is pretty good and
the Andrew Johnson-Laird book "CP/M Programmer's Guide" has an excellent description.
http://www.geocities.com/homeofoscarvermeulen/cpm.html?200811#Directory
Please bear in mind though, I am not a CP/M guru or even an expert on vintage computers or
electronics. I am but a child student at the feet of the real masters. Allison, Chuck, Mike,
Howard, Dave, et al, have probably forgotten more about CP/M and vintage computers than
I'll ever know.
One of the benefits of building your own computer from scratch is it forces you to learn the
practical aspects of those theoretical concepts of computing you probably learned in college. I
know I have and that is why this hobby has paid for itself many times over for me. I can only
recommend diving in and building something. In my engineering day job, we tend to focus on
the more business aspects of things, however, I am expected to keep technically current and
there is nothing better than grabbing the hot tip of a soldering iron to remind you which is the
business end...
At any rate, things are going well today. I contacted my friend who is a simulator expert and
he has a preliminary version of the N8VEM coded up in a popular computer simulator. I tried
a pre-release version already and it works so well I was able to code up a revised CBIOS to
support the 1MB ROM as the F: drive without ever touching the SBC itself. Now I can run the
simulator and do all the programming on the nice PC in a comfortable chair. When I am
satisfied it is working, take the resulting ROMIMAGE.BIN on a floppy disk downstairs, burn
an EPROM, plunk it into the SBC and presto! instant working program.
Normally debugging the CBIOS on target hardware can be a chore but now it is a breeze. I
updated the CBIOS and now the F: drive contains the CP/M transient programs. I am going to
upload a new set of N8VEM software tonight. Once I get clearance from my friend to release
the simulator, I will do that as well assuming he will release it. I am pretty confident he will
but just in case, I will hold off until he gives explicit permission to publish.
Soon you'll probably be able to take the N8VEM SBC out for a test drive on your PC to see
how it works for you. Literally its "try before you buy" to see how the system works before
investing in the PCB or the parts needed to build it.
Which brings up another point, it is way off topic but please let me digress; if you had a nearly
empty 1MB ROM disk on a SBC what sort of programs would you put on it? My thinking was
the basic CP/M transient programs would be cool. Now that those are there though I
recognize that takes up practically no space at all. Of the 992K available, the CP/M transient
programs only take up about 56K leaving 926K available for other programs. Got any ideas?
Probably a good start would be a utility tool set with a decent editor. ED is *not* your
friend. ;-)
Regarding my curiosity about ROMIMAGE.BIN file, I noticed that there are rows
-11-
after rows of
$0 zerrrros there that reminded me so much of "my own bank account"!! :violin:
I guess it hit a nerve in me or something...:happy7:
Yes, that is correct. Most of the 1MB ROMIMAGE.BIN is empty. It is just waiting for some
worthwhile information to add to the F: drive and essential utilities for the A: drive as well. I
still have to hand code the tiny utilities into the A: ROM drive. I was thinking I would add the
IDE drive format utility and maybe a utility to get at the NVRAM in the DS1302. There is no
hurry right now though.
As for the bank account, I think we can all appreciate that feeling from some time or another...
:-) My goal is to keep the cost as low as possible and just offer the PCB. The rest of the parts
can be obtained in many ways to keep costs down. My recommendation is to raid the junk box
first, then obsolete/junk PCs and/or scrap electronic equipment. I suspect an enterprising
person could recover most if not all the parts necessary from scrap recovery of a few PC
boards. All of the components were selected with that idea in mind. I admit the 512Kx8 SRAM
will be a little more difficult.
Would you please take your time (????) and explain a bit more about addressing on
your N8VEM board?
1- Signals such as CS_CFG, and CFG...
2- Logic to ensure upper Ram is always enabled
The signals with the CS_ prefix are used for IO decoding and stands for Chip Select. There is
some IO address decode logic which detects when the CPU is requesting the onboard IO
devices. Specifically, any time the CPU is requesting IO (/IORQ low) and the address on the
lower 8 bits of the address bus are in the $60-7F range.
When those conditions are met, the 74LS139 demultiplexer narrows it down further into
specifically what IO device is being requested. It generates "Chip Select" signals for the 8255
PPI if the address is $60-$67, the 16550 UART for $68-$6F, the RTC for $70-77, and the
MPCLs for $78-7F. The "Chip Select" signal is normally high but when the CPU wants to
connect to a specific IO device, it pulls the devices "Chip Select" pin low to force the device
out of "tristate mode" and actively on to the buses. Each of the CS_* lines go to the chip select
pins on the various IO devices.
The normal state for IO devices when not being specifically accessed is to be in tristate mode.
They are physically connected but all the inputs are in a very high impedance state so they act
like they are not present in the circuit.
Regarding the logic to ensure the Upper RAM is always selected is something different and
relates only to memory mapping. One thing I found during the design phase is the CPU has to
have some region of memory which is essentially permanent so it can retain its own context.
There are two memory pages, the lower 32K and the upper 32K, and the lower 32K page is
switchable. As a result, the 74LS32at U15 ensures the upper 32K page ALWAYS goes to the
same region of the 512K SRAM (A15, A16, A17, A18 all high). No matter what the CPU does
to the MPCLs to reconfigure memory, it is ensured that the program actually making the
changes (assuming it is in the upper 32K RAM page) is always present in the address space. It
may seem silly but you'd be surprised at how easy it is for a CPU to manipulate memory and
suddenly it loses all context and crashes.
After reviewing the schematic, I noticed the terminology I used during the hardware phase is
not the same as what I described during the software phase. I'll update the schematic to make
sure it is more consistent with the terms used in the software source code. It is confusing
when I use two different terms to refer to the same item.
Would you please explain about "ECB data flow direction control"?
-12-
How does it switch direction?
The ECB bus control is in two parts; the address/control lines and the data lines. I'll explain
the address/control lines first since those are easier.
The address/control lines are "export only" from the SBC perspective virtually all the time. In
other words, the address/control lines are repeated from inside the SBC onto the ECB but not
vice versa. The only exception to that is when something on the bus asserts bus control by
lowering the /BUSRQ line. In that case, the CPU goes into BUSRQ mode and the ECB places
the address/control lines into the SBC. Again, this is a pretty rare scenario but it is possible
and the SBC supports it if and when a "bus mastering" peripheral is ever made. Possibly
another CPU card could do this.
The SBC data lines are "import and export" depending on the situation. Normally, the SBC
exports the data lines onto the ECB and does not import them. There is two exceptions
though; first is the /BUSRQ being pulled low by a yet undesigned peripheral which is pretty
rare, and more likely is the SBC CPU has made a IO request READ (/IORQ goes low and /RD is
low) AND the IO address is outside of the internal SBC IO range ($60-$7F). In other words,
the CPU is requesting to IO reads to IO address EXTERNAL to the SBC.
In all cases, it is fairly rare for the SBC to be pulling information (address, control, or data) in
from the ECB. Normally, it just transmits the internal CPU bus onto the ECB for peripherals to
observe and act on.
Now you may have noticed one peculiarity about this implementation of the ECB. The SBC
supports CPU MEMORY WRITES (/MERQ low and /WR low) onto the ECB but it does NOT
support CPU MEMORY READS from memory on the ECB. The address, control, and data lines
are all there to perform the task but the SBC internal bus control logic is limited for the sake
of simplicity. Also, the 1M ROM and 512K RAM is likely sufficient for actual real memory for a
relatively simple CP/M or monitor based system. More than that would probably go to a
secondary store like a disk drive.
If and when there is ever a next generation SBC, I will probably change the bus control logic
to allow CPU MEMORY READS across the ECB. The modification would require changes to
the RAM/ROM memory selection logic to allow RAM disabling in order to leave the lower 32K
page fully deselected (ie, nothing is there at all, no internal RAM nor ROM) so the ECB
peripheral memory would have a "hole" in the CPU address space to exist in. Also, the bus
control logic would be changed to allow changing the data bus direction flow in to the SBC
from the ECB whenever the SBC requests a memory write from the lower 32K memory page
AND the lower 32K memory page has been disabled.
Probably, I could have made those modifications in the initial design but I put them off to
lower the risk down on this SBC design. I had strayed off my prototype already in a few areas
and I wanted to make sure the PCB version was fairly close to prototype to increase the
likelihood it would work. PCB respins are expensive in terms of time and money so risk
introduced by "feature creep" is highly undesirable.
In practical terms, having an IO only ECB is not a limitation for all the peripherals I would like
to make. Virtually all of the Z80 style peripherals communicate via a IO ports. Even the "pipe
dream" video cards (SY6545 and TMS9918) use IO ports only. What would be more difficult to
implement would be ECB memory expansion (RAM/ROM) or memory mapped peripherals like
a 6845 VDU. However, even those are possible by just using IO ports and latches to simulate
the memory accesses. In other words, we are a LONG WAYS away from ever encountering
this theoretical limitation and if and when it ever does get realized, there are relatively simple
fixes to either get around it or resolve it as needed.
1- what is the role of A1 and A2 in extended Ram/Rom addressing and why?
2- Who/What is taking care of stack manipulation when in extended addressing
mode?
The A1 and A2 are used in the IO decoding of the RAM or ROM MPCLs. Remember, Z80
-13-
circuits and peripheral chips are all active low logic (ie, when high = not enabled, when low =
enabled) The OR gate acts like an AND gate in "active low" logic mode.
If A2 = 0 and A1 = 0 and /CS_CFG = 0 then /CS_CFG1 = 0 (ie, enable the chip select on the
RAM MPCL chip.)
If A2 = 1 and A1 = 0 and /CS_CFG = 0 then /CS_CFG2 = 0 (ie, enable the chip select on the
ROM MPCL chip.)
The "active low" logic has a nasty tendency to turn all of what you learned in school on its
head but after you work with it a while it starts to make sense.
Regarding the CPU STACK while in extended addressing; the stack is set in the upper 32K
memory page because it is permanent. This is one of the many reasons why the upper 32K
*must* be fixed is that the CPU has to be able to depend on being able to correctly access its
stack during memory map manipulations. If the stack is $FF00-$FFFF and that 32K RAM
page is permanently fixed to the same physical RAM 32K block then the CPU is assured that
when it pulls its context off the stack (ie returns from an interrupt or subroutine) it gets the
right stuff and not some random garbage that just got paged in.
You'd be surprised at how hard it was for me to learn that particular lesson. Lose the stack
and the CPU quickly goes insane! CPU context bugs are tough and can be hard to get your
head around all the permutations and combinations it can manifest itself. Stack loss is just
one of many... accidentally trashing a good stack is another as is changing the RAM context in
midstream due to a memory page switch (ie, never execute code in the lower 32K memory
page while switching memory page context!). Hopefully, this clarifies things a bit!
1- what is the role of A1 and A2 in extended Ram/Rom addressing and why?
...The A1 and A2 are used in the IO decoding of the RAM or ROM MPCLs.
My bad...and thank you for clarifying it Andrew! I was under the impression that
you will be using the Data lines to enable and establish the Ram/Rom page, but
you are actually using the Address lines in addition to Data lines. So you would be
using:
Out Ad, Da
where, Ad represents A7 A6....A2 A1 A0 and Da represents D7 D6....D0 .
Why aren't you using A0?
Well, sort of. Yes, the address lines are used by the IO decoding circuit to identify the
appropriate MPCL (RAM or ROM) and the data lines set the values in MPCL. However, the
CPU address or data lines do not explicitly set the extended address lines on the RAM or the
ROM, the CPU only tells the MPCL to do it.
It is a subtlety but an important one; the MPCLs act effectively as an extension of the CPU for
higher memory accesses and they are accessed as IO port devices. Otherwise the CPU would
have no way of controlling the memory in excess of 64K using its 16 address lines.
In other words, the CPU manipulates the MPCLs and the MPCLs control the RAM and ROM
extended addressing. It is an indirect relationship but it works. Of course a Z80 with a 20, 24,
or 32 bit address bus would make this unnecessary but then you'd have an 8088, Z8000,
etc. :-)
PS, I am not using A0 as part of the IO decoder as each device is allocated an 8 address range
for IO ports. It is unnecessary as the MPCLs each have their IO address mirrored across 4
addresses (RAM MPCL is $78-$7B, ROM MPCL is $7C-7F). The reason is the UART requires 8
addresses for control and to keep the decoder logic simple and small, I allow a 32 address
range of IO ports dedicated to the "on board" IO devices (PPI, UART, RTC, and MPCLs).
-14-
...the address lines are used by the IO decoding circuit to identify the appropriate
MPCL (RAM or ROM) and the data lines set the values in MPCL...
The point I am making is that by using an "Out Ad, Da" command you would be
placing the appropriate signals on the lines for the decoding section (MPCL) to
access the IO device. It is the Out instruction that is doing the job.
...I am not using A0 as part of the IO decoder as each device is allocated an 8
address range for IO ports. It is unnecessary ...
I am saying that you could have used A0 & A1 instead of A1 & A2, but you just
chose A1 & A2 instead.
Oh, I see what you are saying... yes, the OUT instruction is used for setting the extended
addressing. The CPU uses data and address lines to with the OUT instruction accessing the
MPCLs.
I could have used the A0 address line as part of the decoding and it would have worked. My
thought was to keep the RAM MPCL IO port in on region ($78-$7B) and the ROM MPCL in
another ($7C-$7F). Using A0 would have caused the IO ports to alternate on even/odd
addresses but since practically speaking you really only access a single IO port how they are
mirrored is not much of an issue.
If I had more PCB room, I would change the IO decoding logic to be a lot more specific and
only the minimum necessary IO ports and reduce the usage of IO address space. However, in
order to keep the design simple there was some trade off with efficiency. Its design artifacts
like this which make using large PCBs and/or custom chips so appealing but of course that
drives cost. Its all a trade off in the end...
Great questions and good observations! Thanks and please let me know if there are any other
aspects I can help with!
Looking at the schematics for your N8VEM board, some clarification would be very
helpful regarding the role of A15:
1- whenever A15=1 (high) --> Ram is selected
2- whenever A15=0 (low ) & Rom is NOT enabled (Rom_Enable=1) --> Ram is
selected
3- whenever A15=0 (low ) & Rom is enabled (Rom_Enable =0) --> Rom is selected
4- whenever A15 = 1 --> we are in the higher 32k
5- whenever A15 = 0 & Ram is selected --> we are in the lower 32k
Higher 32k, one page only
A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
1 - - - - - - - - - - - - - - -
1 1 1 1 - - - - - - - - - - - - - - -
A'18 A'17 A'16 A'15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
Lower 32k, 8 pages
A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
0 - - - - - - - - - - - - - - -
- - - 0 - - - - - - - - - - - - - - -
A'18 A'17 A'16 A'15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
where, A' is A_Ram in schematics
- can be any binary value.
-15-
Generally speaking, stack pointer SP has no idea which page we are in, and I
assume it
always refers to the higher 32k where our main program is located. Thus any line
of
program placed on other pages that uses Call or RET would end up in the LA-LA
land unless
we can devise a very sophisticated stack manipulation manager.
Any comment would be much appreciated...
Yes, I think you have it regarding A15 and the memory paging circuit. Thanks, yours is an
excellent description and that was probably one of the more challenging aspects of getting the
home brew prototype to work.
While CP/M is running, the only RAM pages that should have any programs executing in them
are the very top (upper 32K; A15, A16, A17, A18 all high) and the very bottom (lower 32K;
A15, A16, A17, A18 all low). That is where CP/M has its TPA and main memory. The rest of the
RAM is basically just a block device (RAM drive).
The design theory is CP/M and the stack would exist in the upper 32K so that in any event, the
CPU would retain proper context information. There is no guarantee though as programmers
could write programs to run *ANYWHERE*, even from within the ROM (which isn't a bad idea
either, it sure would save TPA space by shrinking the CBIOS). The only program that exploits
this ROM "execute in place" feature is the loader but it is theoretically extendable to any
program. Similarly programs could execute in the other RAM pages as well but stack
management becomes an issue.
However, *in theory* it is possible to have programs executing anywhere in the RAM but as
you pointed out it is the responsibility of the program designer to keep track of CPU and
memory context. That is the hazard of executing any program in bank switched memory and
not unique to this SBC design.
If any advanced operating systems come out with support for this platform, they'll have to
take this fundamental design approach into account. I am pretty sure there are some Z80 real
time OS's around so it is possible but fairly unlikely. I suspect most people will be thrilled to
run the monitor and CP/M (I know I am!) although you never know what people will do. :-)
Well, since you are helping create some great detailed technical documentation (theory of
operations) for the "N8VEM" by extracting this information out of my brain maybe there are
some other angles people would like to try?
I got asked a question about the "parts list" for the SBC which might be helpful. My plan was
that the schematic and the PCB layout were sufficient to select parts but maybe people would
be more comfortable with a formal Bill Of Materials? Detailed building instructions wouldn't
hurt either but I think we need to get some PCBs out there to do that...
I don't know where I should post this, but for the sake of consistency,
I go ahead and post it here :) !
I have always had this question about handshaking procedure for terminal
emulators; some SBCs use only null cables and some others use standard serial
cables. Would you please explain about the handshaking procedure for an
emulator such as Hyperterminal?
There is a similar thread on the N8VEM discussion board. Seth was able to get his SBC to
work using his serial cable like this:
[N8VEM -------- 9-pin DSUB]
2 (DSR) ------- 4
3 (RX) -------- 3
5 (TX) -------- 2
-16-
7 (DTR) ------- 6
9 (GND) ------- 5
Seth posted photos of his serial cable so you can see it up close.
http://groups.google.com/group/n8vem/t/8730736c05641986
My cable is a bit different since I am using HyperTerm and like to use hardware handshaking.
PC DB25 (9 to 25 pin cable) SBC (25 pin female)
2 TD----------------------RD
3 RD----------------------TD
7 GND---------------------GND
6 DSR---------------------DTR
20 DTR----+----------------DSR
5 CTS----+
It is the same as what you have except pin 20 DTR and 5 CTS are wired
together. This allows hardware handshaking using HyperTerm.
As to whether it is actually using hardware handshaking is probably a
matter for debate but at least it doesn't hang anymore...
Making serial connections between computers, especially the older ones, is a complicated
subject. I can usually make something work with a RS-232 breakout box but I am no expert on
the subject that is for sure. I like to use hardware handshaking whenever I can but sometimes
it isn't an option.
Source:
www.vintage-computer.com
-17-
Comments (0)