C-Z80 Computer live on TV !

The title of this post shure looks promising, but really it only means that I`ve managed to use a regular TV as a monitor for my computerūüôā In my search for most popular and easy to obtain display, a CGA option is an obvious choice: 8-bit ISA Magic Combo Card that I`m currently using in my design, has the capability of CGA RGB output (selectable by jumpers):

Magic_Combo

Monitor type and video adapter mode jumpers are located left to the crystal oscillator. Left jumper is monitor type (here set to COLOR). Right Jumper is video adapter mode (set to CGA here)

Details of this can be found on Total Hardware:

http://arvutimuuseum.ee/th99/v/U-Z/50723.htm

CGA output signals include Red, Green, Blue, Intensity, Horizontal and  Vertical Sync. Horizontal frequency is 15.75Khz, vertical refresh rate is 60Hz. This means that a regular TV with SCART RGB input could be used for displaying CGA video. In order to do this, two issues have to be fixed, first: All signals are TTL, so they have to be converted to analog voltage required by SCART RGB. Second issue is that we need to make a composite sync signal from separate H and V signals. Both problems can be solved with a simple active converter circruit presented here on Vogons forum:

http://www.vogons.org/viewtopic.php?f=25&t=40135&sid=72d4c2a6d81e331e278af5488761c0a2
I`ve made such a converter according to the schematic provided by bjt, and it worked perfectly with my PC XT clone. I`m planning to build another one and integrate it with C-Z80. For now, I`m just borrowing it from my XT.

After preparing the hardware, I could do the software part of the modification. I`ve only used info from IBM`s original Hardware Manual for Color Graphics Adapter, that is available on minuszerodegrees.net:

http://www.minuszerodegrees.net/oa/OA%20-%20IBM%20Color%20Graphics%20Monitor%20Adapter%20(CGA).pdf
John Elliot`s “Colour Graphics Adapter: Notes” article could also be helpful:

http://www.seasip.info/VintagePC/cga.html

Two files have to be modified from previous setup: bootcpm program and CP/M BIOS. For the first one I had to rewrite the video card initialisation routine. For the Bios itself – most of the console output code had to be modified for CGA. The modification proved to be quite easy actually, because MDA and CGA designs are similar and the Hardware Manual describes the inistalisation process in a very simple way. It`s also nice to learn how those cards were designed to work together in a PC system: all I/O and video RAM address spaces are separated, and no conflicts are possible.

Both files are available to download here:

CP/M Bios for CGA

Bootcpm program
If I want to go back to MDA again, I would only need to replace both files with previous ones and change jumper settings on the video card. I could also prepare a set of files for serial console mode.

The final effect of the MDA to CGA migration can be seen on a photo below: C-Z80 Computer outputting to SCART RGB capable TV. An external TTL-CGA to SCART adapter lies on the case of the computer:

CGA_RGB_mode

More disk space, format.asm bugfix:

Donn Stewart from cpuville.com wrote me an email describing a bug he found in his format.asm program, that I`ve modified and used for my design. He noticed, that formatting routine needs the starting sector of each track to be 0 , not 1. This modification helped me to get rid of random problems with garbage in directories and “sector not found” messages that sometimes popped out. Having this fixed, I`ve also made a decision to move to a bigger CF cad, and expand the disk drive numbers to CP/M`s maximum 16 drives, labelled from A to P. Here is the proof:

Disk_Drives

Showing all available disk drives with STAT command

This seems to be a reasonable disk space for some confortable work with CP/M. Below is the link to fixed format.asm. This particular source formats drive numbers 4-15, so not to erase the contents of the four disks I was allready using.

Fixed format.asm

Plans for near future:

  • Keyboard handling routine in CP/M BIOS still needs some tweaking.
  • ¬†I`m thinking about leaving out the VGA display adapter, and use only the ISA card for display both in ROM Monitor and CP/M. This would also enable me to modify the ISA adapter card, so the access to it would be faster (directly connect the address lines to Z80 bus instead of latches).
  • ¬†Test of the printer port on Magic Combo card.
  • Adding some external ports to the case (Z80 bus, 8255 ports,RS232 port, CTC signals, SCART connector)

CP/M 2.2 Up And Running.

Tags

C-Z80 Computer is officialy runing CP/M 2.2 for a few weeks now:

overwiev

As soon as the hardware modifications described in the previous post have been done, I started more serious research about the CP/M itself. Despite my initial worries, it turned out, that  adapting this operating system for a particular hardware wasn`t really that hard. It`s even more obvious, as the system was designed in a way to make it easy to adapt for any computer with 8080/Z80 CPU, with only one important requirement РRAM area starting from addres 0000.
When searching for useful documents, tutorials and examples, I came across this page:

http://cpuville.com/cpm_on_new_computer.html

Donn Steward describes his experiences with setting up CP/M on his Z80 system. The article is very well written, has many links to usefull resources, and includes sources of his own work. After printing the article, and reading it several times I was shure I have everything I need to put CP/M on my own system. I Initially used his source of system`s core, but I had to change some assembler directives in order to make it compatible with TASM. Eventually, I ended up using the source provided by Grant Searle on his Breadboard CP/M project site:

http://searle.hostei.com/grant/cpm/index.html
http://searle.hostei.com/grant/cpm/z80sbcFiles.zip (cpm22.asm in /source directory)

It is basically the same source Donn uses, but adapted for TASM. The source code is a work of Clark A. Calkins, who did a really great job in disassembling it from a working system. This source does not need any changes (except origin address Рfor me it`s D400h for 60K CP/M), and TASM assembles it without any problem. The main part of the work is of course the CP/M BIOS. Donn used the skeletal customizable BIOS code found as an appendix to the official CP/M Alteration Guide. I used the same one, but with Donn`s 8080 to Z80 mnemonic change which saved me a bit of work (except of adapting the assembler directives for TASM). I also used his way of bypassing the unneeded sector translation.The skeleton of the bios was ready to be adapted for my own system. For a quick start and debugging  I decided to use serial port for console I/O operations (const,conin and conout subroutines) as it was just a few lines needed for complete implementation. Next big task was to implement the disk I/O operations. I also stick for now to the default 4x ~250kB disk drive setup in order to leave as much original code intact. Because I use single CF Card as a mass storage, all disk selecting and head-positioning subroutines (home, seldsk, settrk, setsec, setdma, sectran) are just variable settings operations. All the magic is in read and write subroutines.For CF card low-level operations I reused much of the code from my own monitor program. Before they can be used, some assumptions had to be made:

  • To make it easier I`m not using sector deblocking algorithms – I only use 128 bytes of each 512byte sectors.
  • ¬†Some translation scheme is needed for a standard¬† 77 track / 26 sect/track¬† 8″ floppy layout to LBA addressing. I arranged it this way:
LBA3 = 00h

LBA2 = 00h

LBA1 = (up to 4 bits of drive number)(4 upper bits of track number)

LBA0 = (3 lower bits of track number)(5 bits for sector number)

It`s not the optimal soultion (still some space is wasted in addition to using on-quarter of each sector), but really it`s not a problem with today CF Card sizes: the whole 4-disk CP/M space (about 1MB) takes 14bits of LBA address, which makes: (16383sectors * 512bytes per sector) = 8191kB = 7MB.

  • The CF card is divided into 2 regions: FAT16 partition, and remaining space: for CP/M`s exlusive use. For the particular 64MB card I`m using, I set the FAT16 partition to about 40MB. The rest of it – starting from LBA sector 00 01 4A 00 is for CP/M. This offset has to be added to every calculation mentoined in the previous point.

With these considerations, read and write procedures were implemented without much trouble.

Next two problems are:

  • formatting the CP/M disks
  • putting the CPM image into first two tracks on the first CP/M disk.

Donn described those two processes in detail, and also presented his code. As the code is rather straighforward and easy to understood, I didn`t bother to rewrite it from scratch, but rather I modified it for my system:
For “format” the idea is: the bios code contatining all disk-related subroutines should allready be loaded at it`s proper destination (for this I use fload command from my monitor program). Then, the assembled format.bin must be loaded to it`s proper destination (generally anywhere below BIOS area). then we must jump to this code. The program is hardcoded to format 4 CP/M disks and return to ROM Monitor.

format.asm

The “putsys” program writes CP/M image to first two tracks (0 sect. 2-26 and 1 sect. 1-25) of first CP/M disk. Both system and bios images must be loaded into their respective memory locations first using ROM Monitor fload command. Then, the putsys program can be loaded at it`s destination and it`s code may be executed.

putsys.asm

The last problem to be solved before the system may finally start was to write a bootstrap program. It`s task is to place both system and bios images into RAM, switch the memory configuration to all RAM, initialize all needed hardware (serial port, keyboard, video cards, CF card, etc..) and jump to BIOS starting point. Again, ROM Monitor FAT16 subroutines come in handy: binary images are read from FAT16 partition and placed into their RAM locations. Hardware is initialized, memory configuration changed, and jump to BIOS executed as a last step.

bootcpm.asm

For the initial tests I used to manually load bootcpm.bin into memory and jumping to it every time I needed to reboot CP/M. Later, I add a very small modification to the ROM Monitor code: In first few bytes I check if any key is pressed. If it is – the ROM monitor starts as usual. If no key is pressed during hard reset or power on – another piece of code is executed: the FAT16 variable area is being initialized, bootcpm.bin is then loaded into RAM, and the control is being passed to it.

Benefits are:

  • CP/M is always automatically loaded without any additional effort.
  • If ROM Monitor is needed for any purpose – it is easy to switch to it.
  • Because ROM Code always loads the same file stored in FAT16 partition, it is very easy to modify any element of the CP/M boot process: I just need to rewrite any part needed, assemble it and put on CF card right from my PC.

The ROM Monitor modifications are here:

    .org 0000h
    LD HL,0FFFFH
    LD SP,HL    
    call start_skan
    cp 0ffh
    jp z,boot_cpm
    jp START
    .org 0100h
START:

....

boot_cpm:

; FAT16 variables clear

    ld hl,85aeh            ;FAT16 variable block start
    ld bc,02e6h            ;that many bytes to clear

_FAT16_var_clear:

    ld a,0
    ld (hl 
    inc hl
    DEC bc
    LD A,b
    OR c
    JP NZ,_FAT16_var_clear
    call erase_screen
    ld a,kursor_on
    ld (znak_kursora),a
    call clear_line_buffer
    ld a,0
    ld (bufor_flaga),a
    ld (x_kursora),a        
    ld (y_kursora),a        
    ld (timer_kursora),a
    ld (R_SHIFT_PRESSED),a
    ld (L_SHIFT_PRESSED),a
    ld bc,0
    ld (index_bufora),bc    

    ld hl,file_bootcpm
    ld de,bufor_linii
    call copy_fname
    call file_fload
    jp 0c000h

copy_fname:

    ld a,(hl)
    ld (de),a
    inc hl
    inc de
    cp 0
    jp nz,copy_fname
    ret
file_bootcpm:    .db "fload bootcpm.bin c000",0
    .END

After all these steps are made, the computer boots into CP/M system without problem.

However, we start with completly clean system – no files, no external ( “transient” ) commands. We only have few internal CP/M commands. Direct writing of files from a PC to CF Card`s CP/M disks area is out of question – it would be too complicated: we wolud need to consider both disk/track/sector to LBA mapping, and also CP/M filesystem structure. A piece of software had to be written on the PC for this. Instead, as many people do, I used the CP/M`s built-in “SAVE” command¬† to download binary files from RAM memory to disk files. For this purpose, I`ve added a little modification to previously mentoined bootcpm program – just before jumping to bios entry point, it executes a procedure for downloading binary file from PC to RAM via parallel port. It`s the same procedure as in ROM BIOS ( “load” command) , but now it has to work as a separate piece of code, because by the time it is started, the memoryis allready swapped to all-ram, and the destination address is 0100h. After the code has been downloaded to RAM, the rest of the boot process takes place. Afte CP/M has started, we ca issue “SAVE xx filename” command, where xx is the number of 256-byte pages of code (starting from 0100h) to be saved to a choosen filename. Using this procedure I`ve managed to place most important CP/M system files inside the system itself. However, this scheme works only for files that can fit into memory in one piece. For larger files, the proces is slightly more complex: We have to divide the file into smaller chunks (for this I`ve used HJSPLIT v3.0 but any simmmilar software will do.) then, we have to download the chunks into separate files inside CP/M using previous procedure. After all chunks are downloaded we can use “pip” transient command to merge all chunks into one file: the syntax is something like that:

PIP result_filename=chunk.001[O],chunk.002[O],.....

The [O] parameter for each file chunk means that we are working on binary (non ASCII) files. Using this procedure, I`ve managed to download some useful software into the system: Games (Zork1, Sargon, Catchum, Ladder, Startrek), Basic interpreters (two versions of Microsoft Basic) and others.

I`ve tested the system and played around with it for some time, using serial console as input/output. Here are some screenshots of the aplications and system itself:

I`ve encountered lots of problems with terminal emulation standards. Some aplications didn`t look good or were completly unusable. Sometimes there was some configuration programs included for them, so most terminal problems could be solved. I`ve also noticed, that on PC`s side, the most compatible terminal emulation program was Minicom¬† running on Linux. For debugging the console input / output a program “Realterm” for Windows, version 2.0.0.70 proved to be extremally helpful. Thanks to it, I was able to track the transmission of escape characters in both directions.

After I gain some skills in using the CP/M and understanding how an ANSI terminal works, I was ready to move on to the final stage: implementing real hardware keyboard and MDA monitor handling subroutines.

For the keybord it went quite shoothly – I`ve reused most of the code I allready wrote for the ROM Monitor. Only minor changes were needed. Now it works fine. For the display it was more complicated, as basically it reqired to write a complete ANSI terminal emulator. It now works good, and works for most applications. There were lots of issues with performance – scrolling, and cursor positioning were taking too much time, and the display was updating too slowly. Some optimisation were needed, and now it runs fine. Here are some screenshots from actual MDA monitor:

Here is the link to actual version of the BIOS:

bios.asm

CP/M adaptation for my computer system is almost done, and continues to give me a great deal of fun! There are however lots of tiny issues to be resolved and tweaks to be made, so I plan to work on them in near future. Here is the list of thinks I wolud like to correct:

  • Keyboard readout: For this moment, the conin subroutine waits for the key to be released before it is returned to the system. This blocks the system itselffor a short time. I need to change it to non-blocking mechanism with proper debouncing and repeating algorithms.
  • ¬†ANSI compatibility of the display – I`ve addes quite a few escape sequences so far, and many programs works fine. However, there are still some more complicated sequences that I need to write properly.
  • Increase disk space: for now I only use standard, default 4x~250KB disk drives. It will be easy to expand it to 16 disks, but they will need formatting and another, larger CF Card with new partition layout. Some dull work. I`m not planning to change disk parameters – I find no joy in messing with this. I`m quite happy with what I allready have.
  • Make more flexible boot proces: I plan to add some configuration file mechanisms, which will allow me to choose the BIOS operation for particular boot. Some text file could be stored along BIOS, CP/M and bootstrap program. During startup, bootstrap code would check this file, and set some BIOS parameters according to it`s content. This will also include LBA starting point for CP/M partition. This will be a great help when moving to another CF Card would beneeded.
  • Find an easy way of transfering files into CP/M – most desirably by using serial port in some program inside CP/M.
  • Maybe change the MDA mode to something more compatible with modern displays – at least a CGA mode with a converter to SCART RGB, but 8-bit VGA card would be perfect !

CP/M Compatibility Card

Tags

, , , , , ,

The interface to 8-bit ISA card for my C-Z80 Computer is now ready. I`ve addes some additional jumpers for setting address pins A16-A19 on the ISA bus and terminating the AEN signal (grounding it). There are also other ISA signals routed to pinheaders for any possible future uses. The interface is theoreticaly capable of handling CGA card (haven`t tested it yet), for which I`ve also added an 14 Mhz generator connected to “OSC” pin on the ISA bus (I`ve checked that my CGA card does not boot in a PC, when this signal is disconnected, so it`s probably necessary). At this moment I`m using a “MAGIC COMBO” MDA/Hercules/CGA card, which can be jumper-switched to operate as CGA or MDA/Hercules and it also can output either to Hercules mono or RGB color monitor. This latter feature is very interesting, as it is very easy to interface it with regular TV set with SCART connector. The card offers one parallel printer interface as a bonus. From the Z80 side, The ISA card is seen trough three I/O addresses:

  • ffe0h – Video memory buffer (read / write)
  • ffe1h – I/0 access (read / write)
  • ffe2h – Low address latch (A0-A7) (write only)
  • ffe3h – High address latch (A8-A15) (write only)

Here is an example program. It initializes the card to MDA mode, clears the screen and displays a nice looking ASCII art by Joan Stark ( http://www.oocities.org/spunk1111/indexjava.htm ).

 

cat

;Some basic delay routines
DELAY_LONG:     .equ 0597h
DELAY:            .equ 0589h

; IO addresses and pin connections used:
; ffe0 - I/O address for memory write / read
; ffe1 - I/O address for port write / read
; ffe2 - write to low address register
; ffe3 - write to high address register
;Card`s IRQ7 - leave unconnected
;Some signals are terminated:
;
;A12,A13,A14,A15,A18,AEN = GND
;A16,A17,A19 = +5V
;

; *** MAIN LOOP ***
    .org 0d000h
    
start:
        
        call port_setup
        call registers_init

repeat:    
        
        call clear_screen
        
        ld ix,test_string1
        ld hl,0
        call line_write
        
        jp 0000

    ; *** SUBROUTINES ***    

port_setup:
    ; Seting up control port of 6845 CRT controller on MDA card (address 3b8h)
    ; According to "IBM Monochrome Display and Prnter Adapter" hardware reference manual
    ; this must be done before anything else.
    ; value "29h" means: 
    ; High resolution mode: ON, Video Enable: ON, Enable Blink: ON
     
        ld bc,0ffe3h
        ld a,03h
        out (c),a
        
        ld bc,0ffe2h
        ld a,0b8h
        out (c),a
        
        ld bc,0ffe1h
        ld a,29h
        out (c),a
        
        ret


registers_init:
    ; Bulk initialization of 6845 CRT controller`s registers
    ; 16 registers has to be initialised with fixed values
    ; recommended by IBM`s hadware manual for MDA card.
    ; Registers are selected by "Index Register" (3b4h)
    ; Values are entered to "Data Register" (3b5h)

        ld ix,init_data
        ld d,10h
        
loop_regs:
        dec d
        ld a,(ix)
        ld e,a
        call reg_write
        inc ix
        ld a,0
        cp d
        jr nz,loop_regs
        ret


reg_write:
    ; writing value to 6845 register.
    ;Entry:
    ;
    ; D - register number
    ; E - value
        
        ld bc,0ffe3h
        ld a,03h
        out (c),a
        
        ld bc,0ffe2h
        ld a,0b4h
        out (c),a
        
        ld bc,0ffe1h
        ld a,d
        out (c),a
                
        ld bc,0ffe3h
        ld a,03h
        out (c),a
        
        ld bc,0ffe2h
        ld a,0b5h
        out (c),a
        
        ld bc,0ffe1h
        ld a,e
        out (c),a        
        ret


line_write:
    ;Write ASCIIZ buffer to MDA card`s video buffer. Assuming "normal" attribute.
    ;Entry:
    ;
    ; HL = Video RAM position - even address, counted from 0
    ; IX = Start of ASCIIZ buffer of data
        ld bc,0ffe3h
        ld a,h
        out (c),a
        
        ld bc,0ffe2h
        ld a,l
        out (c),a
        
        ld b,0
        ld a,(ix)
        cp b
        ret z
        
        ld bc,0ffe0h
        out (c),a
        inc hl
        
        ld bc,0ffe3h
        ld a,h
        out (c),a
        
        ld bc,0ffe2h
        ld a,l
        out (c),a
        
        ld bc,0ffe0h
        ld a,07h    ;normal attribute
        out (c),a

        inc hl
        inc ix
        jp line_write

clear_screen:
    ;Fills the 4K video RAM with zeros

        ld hl,0f9fh
        
continue_clear_screen:

        
        ld bc,0ffe3h
        ld a,h
        out (c),a

        ld bc,0ffe2h
        ld a,l
        out (c),a

        ld bc,0ffe0h
        ld a,0            ;attribute
        out (c),a
        
        dec hl
        
        ld bc,0ffe3h
        ld a,h
        out (c),a

        ld bc,0ffe2h
        ld a,l
        out (c),a

        ld bc,0ffe0h
        ld a,0            ;empty char
        out (c),a


        ld a,h
        or l 
        ret z
        jp continue_clear_screen;

    ;Fixed 6845 register values - taken from 
    ;"IBM Monochrome Display and Printer Adapter" 
    ;Hardware reference manual.
init_data:
    .db 0,0,0,0,0ch,0bh,0dh,02h,19h,19h,06h,19h,0fh,52h,50h,61h    

    ;Example text to be displayed
test_string1:
   ;.db "--------------------------------------------------------------------------------"
    .db "             *     ,MMM8&&&.            *                                       "
    .db "                  MMMM88&&&&&    .                     MDA/Herc. Demo for C-Z80 "
    .db "                 MMMM88&&&&&&&                         Computer. Full I/O       "
    .db "     *           MMM88&&&&&&&&                         and video memory (32KB)  "
    .db "                 MMM88&&&&&&&&                         access trough Z80        "
    .db "                 'MMM88&&&&&&'                         I/O address space.       "
    .db "                   'MMM8&&&'      *                                             "
    .db "          |\\___/|                                                               "
    .db "          )     (             .              .                                  "
    .db "         =\\     /=                                                              "
    .db "           )===(       *                                                        "
    .db "          /     \\                                                               "
    .db "          |     |                                                               "
    .db "         /       \\                                                              "
    .db "         \\       /                                                              "
    .db "  _/\\_/\\_/\\__  _/_/\\_/\\_/\\_/\\_/\\_/\\_/\\_/\\_/\\_                                   "
    .db "  |  |  |  |( (  |  |  |  |  |  |  |  |  |  |                                   "
    .db "  |  |  |  | ) ) |  |  |  |  |  |  |  |  |  |                                   "
    .db "  |  |  |  |(_(  |  |  |  |  |  |  |  |  |  |                                   "
    .db "  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |                                   "
    .db "  jgs|  |  |  |  |  |  |  |  |  |  |  |  |  |                                   "
    .db "                                                                                "
    .db " 8-bit ISA video card interface is a part of CP/M Compatibility Card for        "
    .db " C-Z80 Computer. The card also implements cold/warm reset and 32/64KB RAM       "
    .db " bankswitching circuits.                               (c) 2016 Michal Cierniak "
    .db 0
    .END

Besides 8-bit ISA slot, I`ve also included two very important circuits on the board. One is Flash/ Extra RAM switching circuit which can replace the 32KB Flash ROM with an additional RAM chip of the same size uppon request Рa single I/O write operation to ffffh port toggles the RS flip flop and the actual chip switching occurs (just like in Grant Searle`s design). The second added circuit is a cold/warm reset circuit, which gives a choice of resetting the whole system, or just the CPU  Рpressing RESET button resets the whole system, and enables Flash ROM. Pressing it with RESTORE button down resets only the CPU. These circuits required few small modifications to the existing hardware:

  • ¬†RESET line had to be split into two parts – CPU and system reset. Reset circuit with CPU RESET signals are routed to new board.
  • ¬†The “ROMSEL” signal on the mainboard had to be routed to new board instead of the FLASH ROM chip directly.
  • ¬†Two new signals are introduced: Flash /CS and ExtRAM /CS – one for selecting Flash chip, and one for selecting extra 32KB static RAM chip.
  • ¬†Previously unused RESTORE button on the keyboard is now pulled up to +5V and used for warm reset together with regular RESET button.
  • ¬†I/O write signal for addres ffffh is taken from universal output port on the motherboard and routed to new add-on board (the original port function can still be used though – the bankswitching operation is meant to be one-time action only).

The schematics, board layout and pictures of the card itself:

Those new features are aimed to give my C-Z80 Computer full CP/M hardware compatibility. Below is an example program, that I`ve used to test the reset and bankswitching circuits. It copies the first 8KB of Flash contents into upper RAM area, preforms bankswitch, copies the 8KB code back to 0000h (which is now RAM area) and jumps to that address – the system is reinitialized but now ROM monitor is running in RAM, and all memory address space is in RAM. This can be checked by performing any write / read operation to first half of the memory space.

; Swaps FLASH with RAM 
; Copies operating system from FLASH to RAM.

    .org 0d000h
start:

    ld bc,0000h
    ld de,0a000h
    
    ;copying 8KB from flash 0000h to RAM at a000h
loop:
    ld a,(bc)
    ld (de),a
    inc bc
    inc de

    ld a,020h
    cp b
    jp nz,loop
    
    ;swapping ram with rom 
    
    ld a,0ffh
    ld bc,0ffffh
    out (c),a
    
    ;copying from RAM at a000h to RAM at 0000h

    ld bc,0a000h
    ld de,0000h
    
loop2:
    ld a,(bc)
    ld (de),a
    inc bc
    inc de

    ld a,020h
    cp d
    jp nz,loop2

    ;jump to RAM at 0000h
    
    jp 0000
.END

 

Some pictures of the installed card in the system:

The whole system is now ready for CP/M. I`m going to do some research about it, and implement it in near future. Before this, I`m going to do some experiments with the video card itself – try the Hercules and CGA modes.

80 column display – a new solution.

I`ve recently spent some time trying to find a way to improve my VGA display board in order to make it capable of displaying 80 column text for future CP/M implementation. It would theoretically be possible, but modifications would include at least a new firmware for Atmega328 and XC9536XL, and also a new, smaller font – something like 5×7. It might also be needed to swap the AVR chip for something larger, like Atmega644.Generally, it would be quite a big challenge. As soon as I started making some brief calculations for this, an interesting idea came into my head: wy not try something completely different? Long ago, I remember doing some research about a standard PC ISA VGA cards, and throwing away that idea very quickly, as I realized, that VGA need to be initialized via it`s BIOS routines, in 80×86 code of course. I heard , that VGA can sometimes even call some routines in PC BIOS, so it would be really a dreadful job to make it do just anything barely useful in Z80 enviroment. However, as a vintage PC collector, I own some MDA/Hercules clone cards and monitors.I was aware that MDA/Hercules are quite simple designs, and after some quick research on MDA card and ISA bus I was pretty shure I`m able to make a standard MDA clone work for my C-Z80 computer. It took just a few hours from nothing to displaying lines of text on a monochrome monitor connected to MDA/Hercules clone!

Two_monitors

 

Here is the card connected to the system:

The card itself is driven only by 8255 chip from my 8255/IDE interface card. Absolutely nothing more is required to make it work (except for some cables), also you don`t nedd to worry about synchronization of video memory access with actual video signals – the card does all this by itself (no snowing or jittery image). Here is a complete schematic of connections I made:

mda_connections

As you can see, the card needs 24 I/O lines and positive RESET signal, just exactly what 8255 offers. In fact, you can even let go 2 lines more – /IOR and /MEMR if you`re not planning to do any read operations from the card`s memory or I/O space. The video function of the card does not use any IRQs or DMAs, no external clock sources are needed,no data multiplexing or anything. Basically, the very minimum you need to do with the card to make it display text is:

  • ¬†Setting the video memory or I/O address lines (12 lines in total for MDA, 15 for Hercules in full mode)
  • ¬†Setting the data lines (values needed to be entered to I/O registers and pure video buffer data)
  • Generating negative pulses on /IOW and /MEMW to feed the card with the data.

For full functionality, /MEMR and /IOR have to be implemented for read operations, and also IO CH RDY signal have to be connected to Z80`s /WAIT line in order to implement a full synchronization for I/O and memory operations.

Below I attach a sample test code. It uses 8255 chip at address 88d0h for communicating with MDA card. I only use MDA functionality here, as it is the easiest option, and require less address lines (only 12 for 4K video buffer). The code initializes the card according to original IBM`s hardware reference manual for “Monochrome Display and Printer Adapter”. After this, it clears the screen, displays some text, waits for a moment and repeats the process.

;Some basic delay routines
DELAY_LONG:     .equ 0597h
DELAY:            .equ 0589h

; IO addresses and pin connections used:
; 
; 0ffd0h - 8255 base address in C-Z80 system
; 0ffd3h - 8255 control register
; 0ffd0h - PORT A (connected to lower address lines of MDA card A0 - A7)
; 0ffd1h - PORT B (connected to data lines of MDA card)
; 0ffd2h - PORT C (connected to upper addres lines of MDA card , and to control lines:
;                  C0=A8 PC1=A9, PC2=A10, PC3=A11, PC4=/MEMR PC5=/MEMW PC6=/IOR PC7=/IOW)
;The MDA card is also connected to +5V, GND and also positive RESET source.
;Card`s IRQ7, I/O CH RDY are not used here - leave unconnected
;Some signals are terminated:
;
;A12,A13,A14,A15,A18,AEN = GND
;A16,A17,A19 = +5V
;

; *** MAIN LOOP ***
    .org 0d000h
    
    start:
        
        call init_8255
        call port_setup
        call registers_init

    repeat:    
        
        call clear_screen
        
        ld ix,test_string1
        ld hl,0
        call line_write
        
        call DELAY_LONG
        call DELAY_LONG
        call DELAY_LONG
        call DELAY_LONG
        
        jp repeat

    ; *** SUBROUTINES ***    

    init_8255:
    ; Basic inititalisation of 8255 chip:
    ; All ports as output, mode 0, 
    ; port C = f0h (to set all control signals of MDA card to logic "1")

        ld bc,0ffd3h
        ld a,80h
        out (c),a
        ld bc,0ffd2h
        ld a,0f0h
        out (c),a
        ret

    port_setup:
    ; Seting up control port of 6845 CRT controller on MDA card (address 3b8h)
    ; According to "IBM Monochrome Display and Prnter Adapter" hardware reference manual
    ; this must be done before anything else.
    ; value "29h" means: 
    ; High resolution mode: ON, Video Enable: ON, Enable Blink: ON
     
        ld bc,0ffd2h
        ld a,0f3h
        out (c),a
        
        ld bc,0ffd0h
        ld a,0b8h
        out (c),a
        
        ld bc,0ffd1h
        ld a,29h
        out (c),a    
        call io_write
        ret


    registers_init:
    ; Bulk initialization of 6845 CRT controller`s registers
    ; 16 registers has to be initialised with fixed values
    ; recommended by IBM`s hadware manual for MDA card.
    ; Registers are selected by "Index Register" (3b4h)
    ; Values are entered to "Data Register" (3b5h)

        ld ix,init_data
        ld d,10h
        
    loop_regs:
        dec d
        ld a,(ix)
        ld e,a
        call reg_write
        inc ix
        ld a,0
        cp d
        jr nz,loop_regs
        ret


    reg_write:
    ; writing value to 6845 register.
    ;Entry:
    ;
    ; D - register number
    ; E - value
        
        ld bc,0ffd2h 
        ld a,0f3h
        out (c),a
        ld bc,0ffd0h 
        ld a,0b4h
        out (c),a
        ld bc,0ffd1h 
        ld a,d
        out (c),a    
        call io_write 
        ld bc,0ffd0h
        ld a,0b5h 
        out (c),a
        ld bc,0ffd1h; 
        ld a,e 
        out (c),a
        call io_write;
        ret


    io_write:
    ; generate short negative pulse on /IOW line of MDA card
        ld bc,0ffd3h
        ld a,0eh
        out (c),a
        call DELAY ;just in case I/O operations would take too long.
        ld a,0fh
        out (c),a
        ret

    mem_write:
    ; generate short negative pulse on /MEMW line of MDA card
        ld bc,0ffd3h
        ld a,0ah
        out (c),a
        ld a,0bh
        out (c),a
        ret


    line_write:
    ;Write ASCIIZ buffer to MDA card`s video buffer. Assuming "normal" attribute.
    ;Entry:
    ;
    ; HL = Video RAM position - even address, counted from 0
    ; IX = Start of ASCIIZ buffer of data
        ld bc,0ffd0h
        ld a,l
        out (c),a
        ld a,0f0h
        or h
        ld bc,0ffd2h
        out (c),a
        ld b,0
        ld a,(ix)
        cp b
        ret z
        ld bc,0ffd1h
        out (c),a
        call mem_write 
        inc hl
        ld bc,0ffd0h
        ld a,l
        out (c),a
        ld a,0f0h
        or h
        ld bc,0ffd2h
        out (c),a
        ld bc,0ffd1h
        ld a,07h    ;normal attribute
        out (c),a
        call mem_write;

        ; delay - just for nice looking printout on screen
        call DELAY
        call DELAY
        call DELAY
        call DELAY
        call DELAY
        call DELAY
        inc hl
        inc ix
        jp line_write

    clear_screen:
    ;Fills the 4K video RAM with zeros

        ld hl,0f9fh
        
    continue_clear_screen:
        ld bc,0ffd0h
        ld a,l
        out (c),a
        ld a,0f0h
        or h
        ld bc,0ffd2h
        out (c),a
        ld bc,0ffd1h
        ld a,0             ;attribute
        out (c),a
        call mem_write    
        dec hl
        ld bc,0ffd0h
        ld a,l
        out (c),a
        ld a,0f0h
        or h
        ld bc,0ffd2h
        out (c),a
        ld bc,0ffd1h
        ld a,0            ;empty char
        out (c),a
        call mem_write;    
        ld a,h
        or l 
        ret z
        jp continue_clear_screen;

    ;Fixed 6845 register values - taken from 
    ;"IBM Monochrome Display and Printer Adapter" 
    ;Hardware reference manual.
    init_data:
    .db 0,0,0,0,0ch,0bh,0dh,02h,19h,19h,06h,19h,0fh,52h,50h,61h    

    ;Example text to be displayed
    test_string1:
    .db "Hello! This is MDA display adapter interfacing Z80 CPU! "
    .db "This is a test program showing how it is possible to use "
    .db "a standard IBM MDA display adapter with Z80 CPU system. "
    .db "This is actually a very simple job, as MDA adapters (and also CGA) " 
    .db "have no BIOSes of their own - there is no need for emulating 80x86 code "
    .db "In order to set up the card`s chipset before regular use. Using MDA "
    .db "adapter is as simple as issuing few simple read/write operations to memory "
    .db "and I/O locations. It would be best to place the card`s interface directly "
    .db "into memory and I/O space of the Z80 CPU system - this would be rather easy, "
    .db "as there are just few I/O addressed in use , and 4KB of video RAM. However, "
    .db "for testing the MDA in my C-Z80 system, I used the most simple solution - "
    .db "8255 Programmable Peripheral Interface chip. "
    .db "This chip gives a total of 24 I/O lines, which is just enough to interface "
    .db "MDA card: we need 12 address lines, 8 bit data lines and 4 control signals. "
    .db "8255 can privide all of these. In addition we need a positive RESET signal - "
    .db "taken from 8255 itself, and of course +5V and GND lines. "
    .db "We assume that there is enough time for I/O and memory operations for MDA card "
    .db "So there is no checking of I/O CH RDY line for this simple test setup. "
    .db "It seems the display adapter has it`s own dual port access to video memory "
    .db "as there is no need for any sync while writing into the video buffer - "
    .db "there is no flickering or snowing while accessing the VRAM. " 
    .db "Of course this greatly simplifies the interface design. "
    .db "The video troughput is acceptable, even with rather complex drive trough "
    .db "8255, not directly from CPU. Making a real interface with latches and "
    .db "buffers will icrease the speed even more. I`ll be working on this "
    .db "solution in near future. When the proper interface is ready, the display "
    .db "subsystem of C-Z80 computer will be ready for CP/M implementation."
    .db 0

    .END

Here I attach some charts from logic analyzer:

There are /IOW/ /MEMW and IO CH RDY signals shown. On the first chart we can see a problem with 8255 itself – it seems, that transition between it`s operational modes causes some sort of noise on the /IOW and /MEMW lines, and therefore IO CH RDY line goes crazy. Before they finally settle down, some random data may be entered into card`s I/O and memory space. This sometimes leads to problems with initialisation – the card just display garbage on the screen. This can be fixed with more sophisticated circuit, or just by interfacing the card directly to Z80 bus. After the problematic first few microseconds, we can see the card`s initialisation process : one pulse for setting the 6845 control port, and 16 pairs of pulses for setting the required 16 registers of 6845. After this, a series of /MEMW pulses appear – the video buffer is being filled with data. You can see, that I/O pulses do not produce any wait states from the card (IO CH RDY stays high), so we are safe here. However, video memory access generates wait states from about 0.5 us to over 1.6 us (shown on later charts). This is not a problem for this circuit – with 8255 we can only make pulses as short as 4,6us, so we are also safe here – the card will easily deal with this data rate from the system itself. However, if we plan to interface the card in Z80 I/O and / or memory space, we need to take the IO CH RDY signal into account – a single /IOREQ pulse from Z80 @ 4Mhz is about 0,58us, so the charts clearly show, that a /WAIT signal has to be used when interfacing the card to Z80 system.
AS you can see, making an MDA/Hercules card to work for any 8-bit CPU is really easy. I can recommend some resources on the web that helped me during this experiment:

Very brief, and very helpful description of 8-bit ISA bus interfacing. Nothing more is really needed to start your own experiments with ISA bus:

http://ece.wpi.edu/~wrm/Courses/EE3803/Labs/isa/

Scanned PDF of IBM`s original Hardware Reference Manual for Monochrome Display and Printer adapter. Good manual, schematics included:

http://www.minuszerodegrees.net/oa/OA%20-%20IBM%20Monochrome%20Display%20and%20Printer%20Adapter.pdf

John Elliott`s page on MDA and Hercules hardware and programming tips. This document covers pretty much everything said in the previous one from IBM, but also explains many things in greater detail, and what`s more important: gives information about Hercules mode of monochrome clone cards, so it can be useful if someone wants to get more from the card than just plain MDA:

http://www.seasip.info/VintagePC/mda.html

I`m really happy that this setup actually works. MDA/Hercules display gives many new possibilities to an 8-bit system. However there are of course disadvantages: MDA/Hercules cards are not easy to come by, and can get quite expensive. For monitors – it`s even worse. There is some hope though: with simple passive adapter, a multiscan VGA monitor can be used , though they are also rare (NEC Multisync 3D for example). There can be also found some specialized LCD monitors and signal converters used as a replacement solutions for MDA CRTs in industrial machines. Last option is a good MDA/CGA clone card like ATI Small Wonder – it can output an MdA/Hercules display to a composite output.

In near future, I`m planning to interface the card directly to Z80 bus, and make a proper adapter for it.

Wooden case design

My friend Wojtek made a wooden case for my C-Z80 Computer. Below is an overwiev of the assembled computer:

set

On the front panel, I`ve placed the power button, reset switch and volume adjustment knob. There are also two LEDs: power LED and Compact Flash Activity LED.

The case is very functional – the top cover can be lifted up together with the front panel. All the hardware is easily accessible this way:

full_front_open

Close up of the inside:

front_open

For now I`ve placed only most important ports on the side and back of the case – VGA and joystick ports, 5V DC jack for power supply:

side

back

I have to decide what type of connectors I`m going to use for all other essential I/O ports, like 8255 ports A,B,C , Z80CTC triggers, Z80 bus signals, etc. They all will probably be placed on the left side of the case.

I`m very satisfied with this case. My friend did an excellent job with it. It`s elegant, functional and very solid (I can easilly place any CRT monitor on the top , and the construction will not protest at all).

As for plans for near future, I`m going to add some additional ports to the case, and generally work on some visual details (maybe some logo, informational plates, etc). I`m also going to write some sample code, some game or demo maybe.

FAT16 file system implementation.

Finally, The FAT16 library for my CZ-80 Computer is now ready. I`ve implemented only basic, most useful features, which the system will most benefit from. The ROM Monitor has been upgraded to version 2.0 now.

Features of my FAT16 implementation:

  • Directory listing
  • File reading
  • File writing
  • File creating
  • File deleting

Limitations:

  • Only root directory, no support for subdirectories.
  • Filenames in 8.3 format – no support for long filenames.
  • Only first partition on the disk is used, others are ignored.
  • File attributes and timestamps are ignored.

FAT16 implementation was very time consuming project. The ROM Monitor code is nearly twice bigger after including the FAT16 library. However, it seems everything is working properly. Some new commands have been added to the ROM Monitor command list:

  • dir – directory listing with automatic paging.
  • type – displays a textfile on the screen, automatic paging included.
  • fload – loads a file into memory at specified address
  • rsave – saves a range of memory into a file
  • bsave – saves specified number of bytes from starting address in memory into a given file
  • del – deletes a file

Detailed descriptions are included in PDF manual in download section. We will now check some examples and illustrate them with screenshots from the system:

First, let`s gather some example files, and place them on a CF card:

2015-08-12_091638

Now, let`s insert the CF card into CZ-80 Computer, and power it on. After issuing the dir command, we can see the contents of the root directory:

IMG_0698

We can see file names with extensions, and filesizes in hex. Now, lets examine the memory from address d000:

IMG_0699

There is only garbage here. Let`s load the contents of “autoexec.bat” to that location. The command is written on the screen. After executing it, we`ll check the memory contents again:

IMG_0700

Yes! The autoexec.bat file was loaded at d000h address in memory! Now, lets change first 3 letters “SET” into “ABC”, and save the modified data into a new file called “autoexec.bak”. The steps are shown below:

IMG_0701

Now, let`s see (with a dir command) if the file was really created:

IMG_0704

Yes, it was! It also has the same filesize as the original file. We`ll now check the contents of “autoexec.bak” with type command, the effect is shown below:

IMG_0705

As expected – the modified memory contents were succesfully saved into newly created file. We will now delete the original file, and see if it is really gone by printing out the directory contents again. All is shown on the screen above.

I`ve also included a small help.txt file in which I`ll keep short command descriptions for convinient use. It can be viewed at any time by issuing “type help.txt” on the ROM Monitor screen:

IMG_0706

There are lots of resources and documentations on FAT16 available on the internet and in many books. I was using only 2 documents:

“Fat16 Interface for MSP430” Application Note by Allan Evans. It is a very nice, clear and simple introduction to FAT16, focused on the use of FAT16 with a small microcontroller. Allan`s note is a good reader, it gave me the feeling “OK, I can do this !” . I highly recommend it for starters:

http://www.digitalspirit.org/file/index.php/obj-download/docs/fat/appnote_fat16.pdf

Second document is a FAT16 File System Spectfication. I found this on the “Maverick OS” project site here:

http://www.maverick-os.dk/FileSystemFormats/FAT16_FileSystem.html

This document is very comprehensive, it contains absolutly everything needed for full FAT16 implementation. The most important part however, is the “Calculation Algorithms” section. All needed formulas are gathered there in one place. Just take and use them!

During my development of the¬† FAT16 library, I was extensively using “WinHex” by X-WAys Software Technology AG. Great tool for debugging and learning – easy to use, very intuitive. I would`nt manage to finish the project without this fantastic tool. Highly recommended.

Compact Flash + 8255 interface card.

Mass storage solution for my C-Z80 computer is now ready. I`ve been doing some research on the CF card lately, and I`ve come to the conclusion that interfacing the CF card in 8-bit true-IDE mode is really easy. In fact, the whole IDE interface proved to be a simple and straightforward way of connecting CF cards and hard drives to 8-bit microprocessor or microcontroller. However, I`ve choosen the CF-card instead of a regular IDE harddrive, mainly because of the 8-bit mode that can be used with CF-Card in true-IDE mode. Hard disks are using 8-bit data bus for commands, but a 16-bit one for the actual data. There is no problem in using a standard IDE hard disk with 8-bit only interface, but: we are losing half of the drive`s capactity, and what`s more important: we cannot use any standard filesystem in this way.

I`ve been taking some tips in my design from these sites:

Grant Searle`s CP/M machine:

http://searle.hostei.com/grant/cpm/index.html#Schematic

Grant says he used CF cards connected directly to Z80 bus without any problems. I wasn`t so lucky though: While breadboarding I`ve discovered that only one card worked correctly when connected directly (SanDisk 2GB). Others that I`ve tested didn`t worked (Cisco 64MB: every 3-4th byte read was corrupted, Kingston 4GB – freezed the system, probably was permanently selected). After adding 2x74HCT245 buffers everything worked perfectly – all cards gave good readings, even using very long IDE cables.

Daniel Tufvesson`s blog:

http://www.waveguide.se/?article=8-bit-compact-flash-interface

Very nice quick overview of the 8-bit true-IDE mode of the CF card and an excellent source code example – helped me a lot and pushed the work forward.

Peter Faasse`s document on IDE interface for a microcontroller:

https://www.pjrc.com/tech/8051/ide/wesley.html

Absolutely brilliant text on the subject. Clear and simple. Reading it was a pure pleasure. Practical description of IDE registers and commands.

Lo-tech ISA CompactFlash Adapter rev. 2

http://www.lo-tech.co.uk/wiki/Lo-tech_ISA_CompactFlash_Adapter_revision_2

I recommend this design very much. I`ve build my own piece using the schematics provided on the page – it is working perfectly in my PC-XT machine.

My implementation of the 8-bit IDE interface  for C-Z80 computer uses the FFC0h base address. I`ve also added a 8255 Parallel I/O as a bonus. This chip is placed at the FFD0h base address.

Schematics and PCB: I didn`t bother with elegant design at all – some connections are made with cables. D8-D15 pins of the IDE connector have been removed to simplify the design even more.

schematic

board

The assembled card looks like this:

front

back

Connected to the system:

cf_card-installed

Now some tests. I`ve written a small test program which reads one sector of a CF card and stores it in RAM, so it can be examined with ROM Monitor`s “dump” command. The sector addressing uses LBA mode. As an example,the program will read the MBR of a CF card. Here is the code:

DELAY:            .equ 04ceh
DELAY_NORMAL:    .equ 04eah
DELAY_LONG:        .equ 04dch
x_kursora:            .equ 85a8h
y_kursora:            .equ 85A9h
write_message:        .equ 0619h
erase_screen:        .equ 04f8h

    .org 0a000h

start:

    call erase_screen
    call cf_rdy_wait
    call cf_init
    call cf_info
    
    ld a,0h
    ld (lba0),a
    ld a,0h
    ld (lba1),a
    ld a,0h
    ld (lba2),a
    ld (lba3),a

    call cf_read_sector
    
;    ld ix,buffer
;    call cf_sector_descramble
    

    
loop2:    jp 0000

cf_read_sector:
    call cf_wait
    call cf_set_lba
    ld bc,0ffc2h
    ld a,1            ; czytamy 1 sektor
    out (c),a
    call cf_wait
    
    ld bc,0ffc7h
    ld a,20h
    out (c),a    ; sector read command (20h) to command register (base+7)
    
    call cf_error_check
    ld ix,buffer
    call cf_read
    ret

cf_set_lba
    ld a,(lba0)
    ld bc,0ffc3h
    out (c),a
    
    ld a,(lba1)
    ld bc,0ffc4h
    out (c),a
    
    ld a,(lba2)
    ld bc,0ffc5h
    out (c),a    
    
    ld a,(lba3)
    ld bc,0ffc6h
    
    and 0fh        ; mask 4 MSBs of LBA3 byte
    or 0e0h        ; sets LBA mode + MASTER drive
    
    out (c),a
    
    ret
    

cf_rdy_wait
    ld bc,0ffc7h
    in a,(c)
    and 40h
    jp z, cf_rdy_wait
    ret

cf_wait:

    ld bc,0ffc7h
    in a,(c)
    and 80h
    jp nz,cf_wait
    ret

cf_init:

    ld bc,0ffc7h
    ld a,04h
    out (c),a
    call cf_wait
    
    ld bc,0ffc6h
    ld a,0e0h
    out (c),a
    
    ld bc,0ffc1h
    ld a,01h
    out (c),a
    
    ld bc,0ffc7h
    ld a,0efh
    out (c),a
    call cf_wait
    call cf_error_check
    ret
    

cf_error_check:
    ld bc,0ffc7h
    in a,(c)
    and 01h
    jp z,no_error
    ld ix,error_msg
    call write_message
loop:
    jp loop
    

no_error:
    ret
    

cf_read:
    call cf_wait
    ld bc,0ffc7h
    in a,(c)
    and 08h
    jp z,no_more_data
    ld bc,0ffc0h
    in a,(c)
    ld (ix),a
    inc ix
    jp cf_read
no_more_data:
    ret

cf_info:
    call cf_wait
    ld bc,0ffc7h
    ld a,0ech
    out (c),a
    ld ix,buffer
    call cf_read
    ret

cf_sector_descramble:
    
    ld b,0ffh

cf_descramble_continue:
    
    ld a,(ix+1)
    ld d,(ix)
    
    ld (ix),a
    ld (ix+1),d
    
    inc ix
    inc ix
    
    djnz cf_descramble_continue
    
    ret
    
    
error_msg:
.db 10,”CF Error.”,10,0¬†¬† ¬†

lba0:
.db 0
lba1:
.db 0
lba2:
.db 0
lba3:
.db 0
.db “**********************************”
buffer:    .FILL 1024,0

.END    

And here we can see the results from the “dump” command. The whole 512byte MBR sector of a CF Card.

dump1

dump2

dump3

We can compare the results with a dump from Winhex, according to this program, the first sector looks like this:

winhex

It seems the CF-Card interface is working fine.

The 8255 chip was tested only in a basic way. I`ve initialized it with “output ffd3 80” command to set all ports to output, and observed the voltage on port B pins when executing “output ffd1 ff” and “output ffd1 00” commands. The chip worked as expected: voltage changed from 0V to ~5V.

Plans for the future:

Implementing FAT16 – It`s quite a challenge when programed in Z80 assembly, but there are lots of very good resources on the web, and I believe it could be done.

Bank switching – A small step towards CP/M in the future. I`ll add a small add-on board on the mainboard, that will allow me to disconnect the ROM memory and place 32K ram chip in it`s place. This way there will be 64K RAM available to the system after booting (ROM code will be copied into the RAM during boot)

Case design – I`m going to ask a skilled craftsman for help in design of a wooden case for the computer.

New features, first game !

I`ve been working on some software side of C-Z80 Computer project. Here are the results:

I`ve added a new Monitor command for downloading data and code to RAM using 16450 UART board.It`s syntax is very simple:

sload <16-bit destination address in hex>

The command waits for begining of a transmission on serial port. After receiving the first byte it stores it in RAM at given address. Then, all following bytes are read and stored in appropriate memory locations. After detecting too much idle time, the command assumes, that it has just received the last byte, and exits displaying a confirmation message. The UART is configured for a fixed value of 9600 baud (most compatible in my opinion). All possible UART problems are handled and indicated by error messages (buffer overrun, framing error, break condition).
The next new feature is the graphics mode of the VGA display board.Initialy, the firmware written for VGA display board`s Atmegs328P chip was only able to render text, having ASCII characters patterns stored in program memory. As I mentoined in earlier post, With 2KB of RAM in Atmega328P it was theoreticaly possible to display 160×100 graphics in one colour (1 bits per pixel: (160×100)/8=2000 bytes). Altough it prooved to be very tricky job considering Atmega`s limitations – both RAM and timming requirements for VGA signal generation, I`ve finally managed to implement the graphics mode in my display board. What`s more: video memory seen form Z80 side looks like a linear framebuffer. In Z80 code, when I want to switch to graphics mode I have to execute following code:

    ld bc,3128h    
    ld a,0ffh
    out (c),a
    call DELAY_NORMAL

This switches the AVR chip to graphics mode. a delay is needed to give it some time to clear the video RAM. Withou the delay the display would be corrupted, and cannot be fixed from Z80 side. Now all individual pixels of 160×100 graphics mode can be addressed with single OUT instruction: BC register holds the coordinates (b=y c=x) and a value of 0 or ffh passed to chosen port turns off or on corresponding pixel. Below is a code to switch back to text mode:

    ld a,0
    ld bc,63a7h
    out (c),a
    ld bc,63a0h
    out (c),a
    call DELAY_NORMAL

The addresses and OUT instructions are much different this time, as text and graphics modes use completly different address decoding schemes inside AVR code. Those new features of my C-Z80 computer can be seen on the video below. I use a standard Atari-style joystick plugged into input port on the motherboard (with pullup resistors inside db9 socket) and a 7segment LED display, to show the output port status:

The CTC interrupt example and Snake game sources can be checked in the download section. I`ve also included a new version of ROM Monitor sources (with UART command included) and an updated issue of User`s Manual.

I`ve decided to choose a Compact Flash card as a mass storage for my project. There are few reasons for that:

  • Broad availability and popularity
  • Low price
  • Simple 8-bit interface for microprocessor bus.
  • Possibility to use as a disk drive for CP/M system in future.

As the CF-card interface to Z80 will be so simple – just an address decoder and some passives, I`m planning to add a 8255 chip as a bonus on that card. It could be used for any I/O purpose possible (maybe a printer interface for example ?)

CTC Board ready. Future plans.

Assembly of the CTC board is completed. I`ve added a jumper for disabling interrupt signal if needed, and I`ve also placed a goldpin header with output and input  signals from the CTC:

Channel 0: ZC/TC0 / CLK/TRG0

Channel 1: ZC/TC1 / CLK/TRG1

Channel 2: ZC/TC2 / CLK/TRG2

Channel 3: CLK/TRG2

This header will be available for any peripheral device in the system. It can also be used for cascading  output from one channel to another inside the CTC itself.

ctc_system 004ctc_system 005

Circuit schematics and board layout design:

2014-12-19_1004452014-12-19_100521

Below We can see the whole system as it looks today. Four expansion cards are visible. From left to right: CTC board, UART Board, VGA display board and sound board:

ctc_system 003

Most of the hardware of my computer is now ready. I only have to decide on the mass storage solution. Also I`m still planning to add an I2C controller to take advantage of some interesting peripherals like RTC clock, EEPROMs, etc.¬† In near future I`ll focus on the programming side of the project for a change. I`m going to add some UART routines (including data/program downloading / uploading ) and test some CTC interrupt functionality. I`ll try to write some form of “sound system” which could allow me to play music in the background using interrupts from CTC. I`m also planning to update the VGA Display board`s firmware to enable graphics mode of 160×100 pixels.

UART Board ready, CTC testing

Today I`ve completed the UART board, here are the photos of the PCB:

ctc-uart 004 ctc-uart 005

I was wondering about the interrupt functionality of 16450. I  haven`t really planned to use it, and was going to disable it for good in the final version of the PCB.However, I`ve decided to leave a possibility to use the interrupts in the future by adding jumpers which allows me to select /INT /NMI or NONE.

Schematics and PCB design are below:

2014-12-17_1342272014-12-17_134341

A Z80CTC chip was also tested today. I`m planning to use the CTC`s interrupt functionality extensvely in C-Z80, so this IC will be connected to /INT pin of the system bus.  The connections were rather straightforward , and besides the CTC I`ve only used 74HCT32 for address decoding. The decoder produces a logical OR between A6,A7 and NAND(A8-A15). Lines A0 an A1 are connected to CS0 and CS1 of the CTC. This setup places the CTC in address range of  ff00h to ff03h. The test circuit is shown below:

ctc-uart 003

The logic probe seen on the upper part of the screen is connected to ZC/TO output pins of channed 0, 1 and 2.  After programming the CTC with folowing commands:

ctc-uart 002

Which starts channells 0,1,2 in timer modes with prescalers of 256 and time constants of ffh, 80h and 40h I observed these waveforms on ZC/TO pins:

ctc-pulses

The period between pulses on channel 0 is about 16ms , on channel 1 Р8ms and on channel 2 Рabout 4ms.  The chip seems to be working fine. Interrupts haven`t been checked yet, but there is no reason they shouldn`t be working also. The CTC will be working with Z80 in interrput mode 2. At this moment I`m not planning to use other interrupt capable devices besides earlier mentoined 16450 which could work on NMI if I would need serial port interrputs  badly.

Follow

Get every new post delivered to your Inbox.