; ; MASTER.Z80 This is the Z80 CPU main monitor program for my system. ; Assemble and SLR's Z80ASM Assembler (Can also use the Cromemco Assembler) ; Use:- Z80ASM MASTER FH ; ; Since V5.4, this monitor is now split into two sections. ; IF you have the V2 Z80 CPU S100 Board, the 4K monitor can reside in two 4K "Pages" in an ; 8K 28C64 EEPROM (or 27C64 UV-ROM). There is the "normal" lower 4K monitor where the A12 ; address line is low. This is the "normal" state upon reset (pin 16 of U17 is low which ; via P39, 7-8 will pull A12 of the EEPROM low, thereby selecting the lower 4K half ; of the 8K ROM. If you are using the original S100Computers Z80 CPU board this ; this is the setup. ; If you have the newer V2 board, outputting to port D3H with bit 1 high, will raise the A12 line ; thereby selecting the top 4K of the EEPROM. Outputting to port D3H with bit 1 low, will bring back ; the lower 4K section again. ; ; Code for the two "versions" of the monitor are: MASTER0 & MASTER1. The LOW version (MASTER0)will ; reside from 0-FFFH in a 28C64 EEPROM. The HIGH (MASTER1)version will reside from 1000H-1FFFFH ; in the same 28C64 EEPROM. Clearly there must be code common to both sections. ; The page switching code is near the start of the monitor. It is ; at the location "ACTIVATE_HIGH_PAGE:" and "ACTIVATE_LOW_PAGE". (See below) ; ; Currently almost all menu options are in the LOW PAGE of the ROM. However because of its ; size, the XModem routine (Menu "C") to download files directly into RAM from another computer ; (over a serial port) resides in the HIGH PAGE. Almost half of the HIGH PAGE is now free for ; further routines. ; ; BTW, within the LOW PAGE code (which normally starts at F000H), there is a small jump table fixed at ; F800H for old CPM V1.4 floppy disk BIOS boot routines. My old CPM V1.4 software counts on ; these locations and (for me) they should not be changed. You can ignore them if you like. To do so ; set the equate "RUN_CPM14" below to FALSE. ; ; To assemble under windows... ; Load Altair.EXE in the Windows CMD box ; do cpm3 ; I: ; I:>Submit master0 ; I:>Submit master1 ; ; Master.HEX is written back to the same windows folder that the PC file "altair.exe" is in. ; If this is not clear see here:- (http://s100computers.com/Software%20Index%20Page.htm) ; ; Programming an EEPROM for the V2-Z80 Board with a PROM burner is a little tricky. ; Using a 28C64 EEPROM and a Wellon VP-290 or VP299 Programmer ; For a monitor at F000H-FFFFH:- ; Load the MASTER0.HEX file, (Make sure the ORG is F000H). ; ; Clear Buffer Options:- 00 ; Load Buffer Address :– 0000 ; From File address use:- F000H ; File Size use:- 1000H ; This will put the code (4K) in the lower “half” of the 8K EEPROM, (usually a 28C64). It can be seen/edited ; at 0000H in the ROM with the Wellon software. You can run this ROM on the S100Computers V2 Z80 CPU board ; just make sure P39 is jumpered just 3-4 (PROM address line A12 always low). You can also run it on our earlier ; Z80 CPU Boards. You can use all your Z80 monitor commands except (currently) the X Command. ; ; To burn an EEPROM that adds code to the upper half of the PROM (and has the XModem command): ; Load the MASTER1.HEX file, Make sure the ORG is F000H. Carefully set the following burner settings ; ; Clear Buffer Options:- Disable <-------- Note ; Load Buffer Address :– 1000 ; From File address use:- F000H ; File Size use:- 1000H ; ; Examine the code to be burnt to the EEPROM, It should start at 0H and Run to 1FFFH with the ; early code at 0h the same as at 1000H. ; ; ; Recent History... ; 26/2/09 Added ability to switch CO/CI to ACIA serial from PC. ; 5/3/09 Adjust RTS/CTS levels for Modem ; V3.5 6/3/09 Set talker messages for new V-Stamp chip. ; 12/09/09 Add SD Systems IO-8 board Serial ports. ; V3.52 16/9/09 Add SD Systems IO-8 Board clock display on signon ; v3.6 21/9/09 Add display command for greater than 64K RAM, removed ; V4.0 10/26/09 Switched in 8255 driven IDE HD Controller (Removed XComp) ; some old commands to make more room. ; V4.1 11/7/09 Added input ports scan/diagnostic ; V4.2 11/14/09 Remove Date (keep time) from Clock (Chip is messed up by CPM3 routine) ; also modified to switch from the SD System assembler to the SLR one. ; V4.21 11/17/09 Removed 8086 jump far setting code ; V4.3 11/18/09 Implement movement of 8086 Monitor code (EPROM) to correct location in RAM space ; V4.31 11/19/09 Check 8086 Monitor ROM->ROM went OK. Added W command. ; V4.32 12/7/09 Turn off any SD Systems 8024 video screen enhancements (flashing, underline etc). ; V4.33 12/25/09 Correct High/Low byte Sector read for IDE board ; V4.34 2/23/10 "O" command, 8086 Far jump to 500H (IF RAM @ FFFF0H), W command boots 8086 from reset at FFFF0H. ; V4.35 3/25/10 "O" command just puts 8086 Far JMP to 500H (IF RAM @ FFFF0H). Done also at each reset. ; V4.4 7/29/10 Removed all SD Systems IO-8. Added S-100Computers I/O board drivers. ; V4.41 7/29/10 Initilization of V-Stamp chip done. Cleaned up Serial port names etc ; V4.42 7/31/10 Switched RTC over to S-100Computers board (Ports A4,A5) ; V4.50 2/7/11 Added Floppy Boot loader for ZFDC board. Still have the Versafloppy loader but no BIOS functions ; V4.51 2/13/11 Check IDE if Boot sector is valid ; V4.52 2/15/11 Pulse CF/IDE cards twice to reset (some) cards properly ; V4.53 2/16/11 Initilize IDE board with IDE RD/WR lines inactive on power-up. ; V4.54 2/28/11 Incoporated new fast multi-sector boot for CPM floppy loading with ZFDC board ; V4.55 2/28/11 "O" command now jumps to SWITCH_8086 (activates 8086) when done ; V4.55a 3/1/11 "O" cmd will just put 33 on Console (temporary 8086 board test) ; V4.56 3/15/11 Re-did IDE drive hardware reset pulse to one (delayed) pulse, then wait for drive ready status. ; V4.57 6/3/11 Set up an equate for IDE drive reset pulse, Fixed Z command (Last version using MM58167 RTC chip) ; V4.6 11/27/11 Switched to Dallas Semiconductor/IBM-PC CMOS-RTC chip & MSDOS Support board for time & dates ; V4.7 3/26/12 Cleaned up IOBYTE options. Added 68000 CPU, I/O to serial port. ; V4.8 10/27/12 Corrected SERIAL_STAT: error. Further cleaned up info on IOBYTE ; V4.9 11/3/12 Added ability (XH, XL) Command to switch to low/high pages in 28C64 EEPROMS (for V2 Z80 Board) ; V5.0 12/18/13 Add "C" menu option to download a ZModem file from a PC/Serial/USB port directly to RAM ; V5.01 12/30/13 Add PC-Printer routines for new parallel Port Board with ST8C34 chip (ST8C4 = TRUE) ; V5.02 1/31/14 Allow output to port EEH 01h activate TMA0* (8086,80286,80386 Boards) and 02h TMA1* (68000 Board) ; V5.03 7/25/2014 Removed error in Z memu command ; V5.04 7/29/2014 Patched date to show correct century ; V5.1 3/18/2015 Added to test module to output "3" on console with 8986 reset (UP8086:) in High RAM section ; V5.2 12/17/2016 Change master/slave signon message ("O" commamd) for more general use (multiple slave CPU boards) ; V5.3 11/27/2017 Fix bug for console I/O to serial port if no Propeller Console I/O board is present ; V5.4 12/20/2017 Completely re-did HIGH/LOW ROM page approach. Page menus are now completely transparent to user ; V5.5 7/26/2019 Corrected Monitor Print Signon with printer active. (Was sending continous 0's, Printer LO: inbalance) ; V5.6 2/23/2021 Added IDE Menu for FPGA_DC Board ; ; ; FALSE EQU 0 TRUE EQU NOT FALSE BASE EQU 0F000H ;Start or EPROM Location (Assume a 2732 or half of a 28C64) ;Note can test running in CPM (set ORG to 100H), BUT disable setting the stack ;by commenting out the 4 lines below SETUP_STACK: ORG BASE ;<--------<<<<<< LOCATION OF START OF MONITOR (HIGH PAGE) ST8C4 EQU TRUE ;TRUE if S100_Parallel_IO Board. False if IMSAI PIO Board SCROLL EQU 01H ;Set scrool direction UP. BELL EQU 07H SPACE EQU 20H TAB EQU 09H ;TAB ACROSS (8 SPACES FOR SD-BOARD) CR EQU 0DH LF EQU 0AH FF EQU 0CH QUIT EQU 11H ;Turns off any screen enhancements (flashing, underline etc). NO_ENHANCEMENT EQU 17H ;Turns off whatever is on FAST EQU 10H ;High speed scrool ESC EQU 1BH DELETE EQU 7FH BACKS EQU 08H CLEAR EQU 1AH ;TO CLEAR SCREEN RST7 EQU 38H ;RST 7 (LOCATION FOR TRAP) NN EQU 0H ;[I] INITIAL VALUE SOH EQU 1 ; For XModem etc. EOT EQU 4 ACK EQU 6 NAK EQU 15H STARTCPM EQU 100H ;LOCATION WHERE CPM WILL BE PLACED FOR COLD BOOT STARTDOS EQU 100H ;LOCATION WHERE MSDOS WILL BE PLACED FOR COLD BOOT FFILE_SIZE EQU 9000h/512 ;SIZE OF 5MSDOS20.COM IN 512 BYTE SECTORS ; ; ;IOBYTE = SENSE SWITCHES AT PORT 0EFH ; ; BIT MAP OF PORT 0EFH:- X X X X X X X X (11111111=NORMAL CONFIG) ; | | | | | | | |..For Z80 Monitor, 0=CONSOLE DATA TO PRINTER ALSO ; | | | | | | |....For 8086 Monitor, 0=Force MSDOS Consol output to CGA/VGA Board instead of Propeller board ; | | | | | |......For 8086 Monitor, 0=Do not initilize MSDOS extra ROMS ; | | | | |........Unused ; | | | |...........Unused ; | | |.............For Z80 Monitor, 0=ALL Consol I/O via ACIA Serial port on S100Computers Serial-IO Board ; | | Remember the serial port is currently set for 38.4K, 1 Stop,NP ; | |...............For CPM3, 0=Force reformat of Memory disk upon any CPM3 cold re-boot ; |.................For CPM3, 0=Write protect Memory disk for CPM3 ; For 8086 Monitor, 0=Prevent doing a JMPF to 500H after 8086 reset (to CPM86 boot) ; Normally a test is made to see if the CPM86 Boot is already in RAM at 500H ; If it is, a 8086 reset will bypass the monitor and go directly there. ; (see Init: in 8086 Monitor) ; Note if 00xxxxxx, This will force hardware diagnostic test. (See code at FFFF0H in the 8086 monitor) ; ; ;-------------- PROPELLER CONSOLE_IO (OR SD SYSTEMS VIDIO BOARD) FOR CONSOLE INPUT & OUTPUT CONSOL_STATUS EQU 0H CONSOL_IN EQU 01H CONSOL_OUT EQU 01H ;-------------- THIS IS MY PORT TO OUTPUT DATA TO HP 4050T LASAR PRINTER (IMSAI 8PIO Board) IF ST8C4 ;If S100_Parallel_IO Board for Printer output PRINTER_CTRL EQU 0C2H ;ST8C4 Control Port PRINTER_STATUS EQU 0C1H ;ST8C4 Status port PRINTER_OUT EQU 0C0H ;ST8C4 Data port PRINTER_ST_LOW EQU 0DH ;OUT STROBE LOW PRINTER_ST_HIGH EQU 0CH ;OUT STROBE HIGH ELSE PRINTER_STATUS EQU 5 ;IN, IMSAI PIO Board PARRELL PORT PRINTER_OUT EQU 5 ;OUT PRINTER_STROBE EQU 4 ;OUT ENDIF DIAG_LEDS EQU 5 ;OUT, Will use this port (either board) initially for diagnostic LED display. ;-------------- S100Computers I/O BOARD PORT ASSIGNMENTS (A0-AC) BCTL EQU 0A0H ;CHANNEL B CONTROL PORT ASSIGNMENTS OF THE ZILOG SCC CHIP ;<--- Adjust as necessary, BDTA EQU 0A2H ;CHANNEL B DATA ACTL EQU 0A1H ;CHANNEL A CONTROL (MODEM_CTL_PORT) ADTA EQU 0A3H ;CHANNEL A DATA (MODEM_DATA_PORT) PortA_8255 EQU 0A8H ;A port of 8255 ;<--- Adjust as necessary PortB_8255 EQU 0A9H ;B port of 8255 PortC_8255 EQU 0AAH ;C Port of 8255 PortCtrl_8255 EQU 0ABH ;8255 configuration port AinBout8255cfg EQU 10011000b ;Set 8255 ports:- A input, B output, USB_DATA EQU 0ACH ;PORT ASSIGNEMENT FOR DLP-USB Controller chip USB_STATUS EQU 0AAH ;Status port for USB port (Port C of 8255, bits 6,7) USB_RXE EQU 80H ;If Bit 7 = 0, data available to recieve by S-100 Computer USB_TXE EQU 40H ;If Bit 6 = 0 data CAN be written for transmission to PC BASE_PORT EQU 0A1H ;For XModem communication routines MODEM_CTL_PORT EQU BASE_PORT ;A1H (Note modem I/O will be on CHANNEL A. Speaker on CHANNEL B MODEM_DATA_PORT EQU BASE_PORT+2 ;A3H MODEM_SEND_MASK EQU 4 SEND_READY EQU 4 ;VALUE WHEN READY MODEM_RECV_MASK EQU 1 RECV_READY EQU 1 ;BIT ON WHEN READY MODEM_ERR_LIMIT EQU 8 ;Max number of Modem serial port re-reads aborting MODEM_RTS_DELAY EQU 1 ;Time to check Modem RTS line (See XMODEM_LOAD & P_XMODEM_LOAD). Not critical. RECVD_SECT_NO EQU 0H ;IX Offset for XModem Recieved Sector Number SECTNO EQU 1H ;IX Offset for XModem CURRENT SECTOR NUMBER ERRCT EQU 2H ;IX Offset for XModem ERROR COUNT ;-------------- S100Computers MSDOS Support Board PORT ASSIGNMENTS CMOS_PORT EQU 70H ;Base Port for CMOS Clock/Date Chip on MSDOS Support Board MASTER_PIC_PORT EQU 20h ;Hardware port the 8259A (two ports 20H & 21H) MasterICW1 equ 00010111B ;EDGE triggered, 4 bytes, single Master,ICW4 needed MasterICW2 equ 8H ;Base address for 8259A Int Table (IBM-PC uses 8X4 = 20H) MasterICW3 equ 0H ;No slave MasterICW4 equ 00000011B ;No special mode, non buffer, Auto EOI, 8086. ;<<<<, ;--------------- PORTS FOR FOR Z80/WD2793 FDC Board S100_DATA_A EQU 10H ;IN, S100 Data port to GET data to from FDC Board S100_DATA_B EQU 10H ;OUT, S100 Data port to SEND data to FDC Board S100_STATUS_A EQU 11H ;Status port for A S100_STATUS_B EQU 11H ;Status port for B RESET_ZFDC_PORT EQU 13H ;Port to reset ZFDC Z80 CPU. STATUS_DELAY EQU 5 ;Time-out for waiting for ZFDC Board handshake signal (~0.5 seconds @ 10MHz) DIRECTION_BIT EQU 7 ;Bits for the ZFDC flags 0 = IN, 1 = OUT DATA_IN_RDY EQU 0 ;Bit for data available from ZFDC board DATA_OUT_RDY EQU 1 ;Bit for data can be sent to ZFDC board STD8IBM EQU 1 ;IBM 8" SDSS Diak NO_ERRORS_FLAG EQU 0 ;No Errors flag for previous cmd, sent back to S-100 BIOS ;Commands to the ZFDC Board:- CMD_RESET_ZFDC EQU 3H ;Reset the WD2793 chip and Board software CMD_SET_FORMAT EQU 4H ;This will select a specified drive and assign a disk format table to that drive CMD_SET_DRIVE EQU 5H ;This will select a specified drive (0,1,2,3) CMD_SET_TRACK EQU 7H ;This will set head request to a specified track CMD_SET_SIDE EQU 8H ;This will set side request to a specified side CMD_SET_SECTOR EQU 9H ;This will set sector request to a specified sector CMD_SET_HOME EQU 0AH ;This will set head request to Track 0 of CURRENT drive CMD_STEP_IN EQU 0BH ;Step head in one track of CURRENT drive CMD_SEEK_TRACK EQU 0EH ;Seek to track to (IY+DRIVE_TRACK) with the track verify bit set on CURRENT drive/format CMD_READ_SECTOR EQU 10H ;Read data from the CURRENT sector (on current track,side,drive). CMD_HANDSHAKE EQU 21H ;Handshake command only sent during board initilization/testing CMD_RD_MULTI_SECTOR EQU 29H ;Read data from multiple sectors starting at the CURRENT sector (on current track,side,drive). ;-------------- PORT(S) TO SWITCH MASTER/SLAVE(S) Z80PORT EQU 0D0H ;4 PORTS ON Z80 BOARD FOR MEMORY MANAGEMENT (& INT Controller on IA Z80 CPU Board) IOBYTE EQU 0EFH ;IOBYTE (SEE ABOVE) SW_TMAX EQU 0EEH ;OUTPUT BIT 0 HIGH FROM THIS PORT LOWERS DMA0* ON THE SMB_V2 (SWITCH IN THE 8086 FAMILY of boards) ;OUTPUT BIT 1 HIGH FROM THIS PORT LOWERS DMA1* ON THE SMB_V2 (SWITCH IN THE 68000 CPU Board) ;OUTPUT BIT 2 HIGH FROM THIS PORT LOWERS DMA2* ON THE SMB_V2 ;OUTPUT BIT 3 HIGH FROM THIS PORT LOWERS DMA3* ON THE SMB_V2 SW_TMA0 EQU 0EDH ;INPUT FROM THIS PORT LOWERS DMA0* (SWITCHES IN THE 8088,8086,80286 or 80386 boards) ;-------------- VERSAFLOPPY-II FLOPPY DISK CONTROLLER COMMANDS ETC. X EQU 50H ;BASE PORT FOR 1791 RSET EQU X+0 ;CONTROLLER RESET ADDRESS SELECT EQU X+3 ;DRIVE SELECT PORT STATUS EQU X+4 ;STATUS PORT TRACK EQU X+5 ;TRACK PORT SECTOR EQU X+6 ;SECTOR PORT DATA EQU X+7 ;DATA PORT CMD EQU X+4 ;COMMAND PORT CIOBYTE EQU 03H CDISK EQU 04H ZERO_L EQU 08H ;Some of my CPM Loader's needs these to be zero! ZERO_H EQU 09H ;(The Non Banked version of CPM3). Need to later see why @TADDR EQU 40H @UNIT EQU 42H ;NEW @UNIT BYTE @SCTR EQU 43H ;SECTOR (compatible with my old CPM2.2 Versafloppy BIOS) @TRK EQU 44H ;TRACK @NREC EQU 45H ;# OF SECTORS @ERMASK EQU 46H ;ERROR MASK @ERSTAT EQU 47H ;ERROR FLAG STORE @IDSV EQU 48H ;6 BYTES (USED FOR TRACK ID COMMAND) @CMDSV EQU 4EH ;COMMAND SAVE @SPSV EQU 4FH ;SP SAVE TEMP2 EQU 51H ;2 BYTE TEMP RECORD @SIDE EQU 51H ;SIDE STORE FOR MSDOS DISK @COUNT EQU 53H ;SECTORS/TRACK for BOOT (Currently unused) @UNITCK EQU 55H ;OLD @UNIT BYTE @RSEEK EQU 56H ;NBR OF RESEEKS @RTRY EQU 57H ;NBR OF RTRYS ADRIVE EQU 58H ;STORE OF A: DRIVE DENSITY ETC TYPE BDRIVE EQU 59H ;STORE OF B: DRIVE TYPE @FDCTYPE EQU 5BH ;0FFH = ZFDC FDC Board Boot, else Versafloppy II FDC Boot, @SEC_SIZE EQU 5CH ;Byte count of a sector fot loader @SSTACK EQU 80H ;SYSTEM STACK COLD EQU 80H ;COLD START ADDRESS FOR CPM FLOPPY (ONLY) BOOT LOADER RDACMD EQU 0C0H ;READ ADDRESS CODE RDCMD EQU 088H ;READ SECTOR CODE WRCMD EQU 0A8H ;WRITE SECTOR CODE WRTCMD EQU 0F4H ;WRITE TRACK CODE RSCMD EQU 008H ;RESTORE COMMAND (Note 3 Ms seek) SKNCMD EQU 018H ;SEEK NO VERIFY FSKCMD EQU 01CH ;FLOPPY SEEK COMAND RSVCMD EQU 00CH ;RESTORE WITH VERIFY COMMAND MSKCMD EQU 01FH ;MINI FLOPPY SEEK COMMAND SRMASK EQU 0FEH ;SECTOR READ ERROR BITS MASK STDSDT EQU 26 ;STANDARD 8" 26 SECTORS/TRACK STDDDT EQU 50 ;STANDARD DD 8" 50 SECTORS/TRACK NBYTES EQU 128 ;BYTES/SECTOR NTRKS EQU 77 ;TRACKS/DISK ;-------------- S100Computers IDE HARD DISK CONTROLLER COMMANDS ETC. IDEAport EQU 030H ;lower 8 bits of IDE interface IDEBport EQU 031H ;upper 8 bits of IDE interface IDECport EQU 032H ;control lines for IDE interface IDECtrl EQU 033H ;8255 configuration port IDEDrivePort EQU 034H ;To select the 1st or 2nd CF card/drive (Not used with this monitor) IDE_Reset_Delay EQU 020H ;Time delay for reset/initilization (~60 uS, with 10MHz Z80, 2 I/O wait states) CPM_ADDRESS EQU 100H ;Will place the CPMLDR.COM Loader here with ;CPMLDR.COM will ALWAYS be on TRK 0,SEC2, (LBA Mode) SEC_COUNT EQU 12 ;CPMLDR.COM requires (currently) 10, 512 byte sectors ;Add extra just in case RDcfg8255 EQU 10010010B ;Set 8255 IDECport out, IDEAport/B input WRcfg8255 EQU 10000000B ;Set all three 8255 ports output ; IDEa0line EQU 01H ;direct from 8255 to IDE interface IDEa1line EQU 02H ;direct from 8255 to IDE interface IDEa2line EQU 04H ;direct from 8255 to IDE interface IDEcs0line EQU 08H ;inverter between 8255 and IDE interface IDEcs1line EQU 10H ;inverter between 8255 and IDE interface IDEwrline EQU 20H ;inverter between 8255 and IDE interface IDErdline EQU 40H ;inverter between 8255 and IDE interface IDEreset EQU 80H ;inverter between 8255 and IDE interface ; ;Symbolic constants for the IDE Drive registers, which makes the ;code more readable than always specifying the address pins ; REGdata EQU 08H ;IDEcs0line REGerr EQU 09H ;IDEcs0line + IDEa0line REGcnt EQU 0AH ;IDEcs0line + IDEa1line REGsector EQU 0BH ;IDEcs0line + IDEa1line + IDEa0line REGcyLSB EQU 0CH ;IDEcs0line + IDEa2line REGcyMSB EQU 0DH ;IDEcs0line + IDEa2line + IDEa0line REGshd EQU 0EH ;IDEcs0line + IDEa2line + IDEa1line ;(0EH) REGCMD EQU 0FH ;IDEcs0line + IDEa2line + IDEa1line + IDEa0line ;(0FH) REGstatus EQU 0FH ;IDEcs0line + IDEa2line + IDEa1line + IDEa0line REGcontrol EQU 16H ;IDEcs1line + IDEa2line + IDEa1line REGastatus EQU 17H ;IDEcs1line + IDEa2line + IDEa1line + IDEa0line ;IDE CMD Constants. These should never change. CMDrecal EQU 10H CMDread EQU 20H CMDwrite EQU 30H CMDinit EQU 91H CMDid EQU 0ECH CMDdownspin EQU 0E0H CMDupspin EQU 0E1H ; ; IDE Status Register: ; bit 7: Busy 1=busy, 0=not busy ; bit 6: Ready 1=ready for CMD, 0=not ready yet ; bit 5: DF 1=fault occured insIDE drive ; bit 4: DSC 1=seek complete ; bit 3: DRQ 1=data request ready, 0=not ready to xfer yet ; bit 2: CORR 1=correctable error occured ; bit 1: IDX vendor specific ; bit 0: ERR 1=error occured ; ; ; ;--------------- PORTS FOR FOR S100 Bus interface to All In One DC board Board ----------------------------------------- S100_STATUS_PORT EQU 80H ;STATUS port to send/get data to/from S100 bus. S100_DATA_PORT EQU 81H ;DATA port to send/get data to/from S100 bus. BOARD_ACTIVE_PORT EQU 82H ;Port to turn on Board Active LED D11 (Note S100 bus or FPGA 82H ports work) SOFT_RESET_PORT EQU 83H ;Reset Handshake status port bits (80H) STATUS_PORTS_RESET EQU 84H ;Reset port IO status bits on DC board FPGA_RTS EQU 01H ;01H if DC Board HAS send data S100_RTS EQU 80H ;80H if S100 Bus HAS sent data ; ; ; ;------------------------------ FPGA_DC BOARD COMMANDS (Reuse some ZFDC commands) ------------------------------------ CMD_SEL_DRIVE EQU 5H ;**** (Re)select an already initilized drive CMD_SET_TRACK EQU 7H ;**** This will set head request to a specified track (ONLY) CMD_SET_SECTOR EQU 9H ;**** This will set sector request to a specified sector (ONLY) CMD_READ_SECTOR EQU 10H ;**** Read data from the CURRENT sector (on current track,(side),drive). CMD_WRITE_SECTOR EQU 11H ;**** Write data to the CURRENT sector (on current track,(side),drive). CMD_FORMAT_TRACK EQU 16H ;**** Format the disk in the of the CURRENT CMD_INIT_DRIVE EQU 30H ;Select AND Initilize the current drive CMD_SET_TRK_SEC EQU 31H ;Set new current TRACK AND SECTOR on current drive CMD_GET_DRV_TRK_SEC EQU 32H ;Get current TRACK/SECTOR on current DC Board drive CMD_CLEAR_SEC EQU 33H ;This will set all current drive sector bytes to a specified byte value CMD_MOVE_SEC EQU 34H ;Copy/Move one sector to another location on current drive CMD_VERIFY_SEC EQU 35H ;Verify two sectors are the same on the current drive CMD_BUMP_SEC EQU 36H ;Point to the next disk sector CMD_BACK_SEC EQU 37H ;This will set "head" to the previous sector CMD_GET_BUFFER EQU 38H ;Get contents of RAM sector buffer on DC board CMD_RD_N_SEC EQU 39H ;Read N sectors CMD_WR_N_SEC EQU 3AH ;Write N Sectors CMD_CPM_BOOT EQU 3BH ;Send CPM Boot image to S100 system (CPM$SEC$COUNT sectors) CMD_DRIVE_COPY EQU 3CH ;Copy one complet drive to another CMD_SD_DISK_STATUS EQU 3DH ;Get status of cards in SD Disk adaptors CMD_START_WATCHDOG EQU 3EH ;Start watchdog timer hardware (not currently active) CMD_GET_NSCTRS EQU 3FH ;Get SEC/TRACK for defined drive CMD_FORMAT_DISK EQU 40H ;Format completely the current disk CMD_LIMIT EQU 41H ;All CMDs will be less than this, error check CMD_FAILED EQU 0FFH ;CMD failed to exacuite completely CMD_COMPLETE EQU 0F0H ;Flag returned by DC board to signal the previous CMD was completed OK ; ; @SECTOR_BUFFER EQU 0E000H ;Location for FPGA_DC Controller DMA sector data buffer in RAM NSCTRS EQU 0FFH ;>>>>>>>>>>> MAX sectors/track <<<<<<<<<<<<<<<<<<< CPM_SEC_COUNT EQU 12 ;Allow up to 12 CPM sectors for CPMLDR CPMLDR_ADDRESS EQU 100H ;Load the CPMLDR at 100H in RAM ; ;---------------------------------------------------------------------------- ; ;JUMP TABLE TO ROUTINES WITHIN THE MONITOR1.Z80 :- ;PROGRAM CODE BEGINS HERE ;FIRST A JUMP TABLE FOR KEY JUMPS INTO THE MONITOR. NOTE THESE SHOULD NOT BE CHANGED BECAUSE ;SOME OF MY OLDER SOFTWARE JUMPS DIRECTLY TO THEM. (WHERE POSSIBLE, TDL's ZAPPLE MONITOR FORMAT IS USED). ZAPPLE: JP ACTIVATE_LOW_PAGE ;INITILIZATION ZCI: JP HIGH_CI ;CONSOL INPUT ZRI: JP NoHighPageError ;This routine resides on the LOW page ROM ZCO: JP HIGH_CO ;CONSOL OUTPUT ZPOO: JP NoHighPageError ;This routine resides on the LOW page ROM ZLO: JP NoHighPageError ;This routine resides on the LOW page ROM ZCSTS: JP HIGH_CSTS ;CONSOL STATUS ZMEMCK: JP NoHighPageError ;This routine resides on the LOW page ROM ZTRAP: JP NoHighPageError ;This routine resides on the LOW page ROM ZSTART: JP ACTIVATE_LOW_PAGE ;JUMP BACK TO LOW PAGE MONITOR START ZTALK: JP HIGH_SPEAKOUT ;SEND AN ASCII CHARACTER TO TALKER (One at a time) ZTALKS: JP HIGH_SPEAKER_CTS ;STATUS FOR SPEECH CTS Line (V-Stamp CTS low when ready) ZDELAY: JP NoHighPageError ;This routine resides on the LOW page ROM ZLSTAT: JP NoHighPageError ;This routine resides on the LOW page ROM ZONLIST: JP NoHighPageError ;This routine resides on the LOW page ROM ZOFFLIST: JP NoHighPageError ;This routine resides on the LOW page ROM ZTIME: JP NoHighPageError ;This routine resides on the LOW page ROM ZDATE: JP NoHighPageError ;This routine resides on the LOW page ROM ZSPEAK: JP HIGH_SPEAK ;SEND ASCII STRING TO TALKER [HL] UP TO '$' ZSERIAL_OUT: JP NoHighPageError ;This routine resides on the LOW page ROM ZSERIAL_IN: JP NoHighPageError ;This routine resides on the LOW page ROM ZSERIAL_STA: JP NoHighPageError ;This routine resides on the LOW page ROM ZLOADER: JP NoHighPageError ;This routine resides on the LOW page ROM ZPMSG0: JP NoHighPageError ;This routine resides on the LOW page ROM ZPMSG$: JP HIGH_PRINT_STRING ;DISPLAY STRING ON CONSOL [HL]=START ADD. '$'=END ZHLSP: JP NoHighPageError ;This routine resides on the LOW page ROM ZBITS: JP NoHighPageError ;This routine resides on the LOW page ROM ZLBYTE: JP HIGH_LBYTE ;DISPLAY [A] ON CONSOL ZHEXSP: JP HIGH_HEXSP ;PUT 16 BIT PARAMETERS ON STACK FROM CONSOL, [C]=PARAMETER # ZCRLF: JP HIGH_CRLF ;SEND CRLF TO CONSOL ZHILO: JP NoHighPageError ;This routine resides on the LOW page ROM ZCONV: JP NoHighPageError ;This routine resides on the LOW page ROM ZDOS JP NoHighPageError ;This routine resides on the LOW page ROM ZPCHK: JP NoHighPageError ;This routine resides on the LOW page ROM ZVBOOT JP NoHighPageError ;This routine resides on the LOW page ROM ZHARD: JP NoHighPageError ;This routine resides on the LOW page ROM ZPRDY: JP NoHighPageError ;This routine resides on the LOW page ROM ZRSTAT: JP NoHighPageError ;This routine resides on the LOW page ROM ZCCHK: JP NoHighPageError ;This routine resides on the LOW page ROM ZZBOOT JP NoHighPageError ;This routine resides on the LOW page ROM ;----------------->>> THIS CODE MUST BE AT THE SAME LOCATION AS FOR THE LOW PAGE ROM CODE <<<--------- ; ACTIVATE_HIGH_PAGE: ; SWITCH TO HIGH PAGE of ROM NOP NOP NOP NOP JP HIGH_MENU_OPTION ACTIVATE_LOW_PAGE: ; RETURN BACK TO LOW PAGE OF ROM LD A,04H ; 04H for MEMORY MANAGEMENT TO OVERLAP + Bit 1 = HIGH PAGE OUT (Z80PORT+3),A JP NoHighPageError ; Will arrive here only IF no address line switch. ; ;----------------------->>> END OF COMMON CODE LOACTIONS <<<---------------------------------- ; ; HIGH_MENU_OPTION: LD A,D ; HIGH PAGE code with 1 in [D] for XMODEM CP A,1 JP Z,HIGH_XMODEM CP A,2 JP Z,HIGH_FPGA_IDE JP INVALID_MENU_ERROR ; The only menu option so far INVALID_MENU_ERROR: LD HL,INVALID_PARM_MSG ; Point Error Message CALL HIGH_PRINT_STRING ; Print string JP ACTIVATE_LOW_PAGE MENU_ERROR: LD HL,M_ERROR_MSG ; Point Error Message CALL HIGH_PRINT_STRING ; Print string JP ACTIVATE_LOW_PAGE NoHighPageError: LD HL,NoHighPageMsg ; "No address line LA13 switch active" CALL HIGH_PRINT_STRING ; Print string JP ACTIVATE_LOW_PAGE ; ; ;<<<<<<<<<<<<<<<<<<<<<< MAIN CONSOL OUTPUT ROUTINE >>>>>>>>>>>>>>>>>>>>>>>>> HIGH_CO: IN A,(IOBYTE) BIT 5,A ;SEE IF SERIAL PORT OUTPUT IS REQ JR NZ,NO_SERIAL ;MAKE SURE TO RETURN CHARACTER SENT IN [A] CALL SERIAL_OUT ;Send data in [C] to Serial Port (Only) JR SDCON5 NO_SERIAL: IN A,(IOBYTE) ;NOTE CHARACTER IS IN [C] BIT 0,A ;CHECK IF OUTPUT TO PRINTER IS ALSO REQ CALL SDCONO ;OUTPUT TO CONSOLE (No Printer) RET SDCONO: IN A,(CONSOL_STATUS) ;SD SYSTEMS OR PROPELLER CONSOLE I/O BOARD PORT AND 4H JR Z,SDCONO LD A,C CP 07H ;IS IT A BELL JR Z,BELL1 CP 0H ;SD BOARD CANNOT TAKE A NULL! RET Z OUT (CONSOL_OUT),A IN A,(IOBYTE) BIT 5,A ;SEE IF SERIAL PORT OUTPUT IS REQ JR NZ,SDCON5 ;MAKE SURE TO RETURN CHARACTER SENT IN [A] SDCON5: LD A,C RET ;RETURN CHARACTER SENT IN [A] BELL1: LD A,06H ;SEND A BELL OUT (CONSOL_OUT),A LD A,0FH CALL DELAY LD A,07H OUT (CONSOL_OUT),A JR SDCON5 DELAY: DEC A ;GENERAL COUNT DOWN TIME DELAY RET Z ;LENGTH SET IN [A] PUSH AF LD A,05H MORE: DEC A PUSH AF XOR A MORE2: DEC A JR NZ,MORE2 POP AF JR NZ,MORE POP AF JR DELAY ;>>>>>>>>>>>>>>>>>>>>>>>>> SPEECH OUTPUT ROUTINES <<<<<<<<<<<<<<<<<< ; ;SPEAK OUTPUT (WILL BE USED TO COMMUNICATE WITH TALKER) ; Note the S100Computers I/O board V-Stamp speech chip will use the initial baud rate ; of of the SCC to communicate with it. This is determines after each reset/slave clear. HIGH_SPEAKER_CTS: ;Cannot get this to work. SCC does not change bit 5 of RR1 ;when E1 sent to WR3 (No Auto Enable). See SCCINIT: IN A,(BCTL) ;A0H BIT 5,A LD A,0FFH RET NZ ;Ret NZ if CTS is High XOR A RET ;Ret Z if CTS is Low HIGH_SPEAKOUT: XOR A,A ;Will try 256 times, then timeout SPXXX: PUSH AF IN A,(BCTL) ;(A0), Is SCC RX Buffer empty AND 04H JR NZ,SENDS ;NZ if ready to recieve character POP AF DEC A JR NZ,SPXXX RET SENDS: POP AF LD A,C OUT (BDTA),A ;(A2), Send it RET ; ;SPEAKTOMM THIS IS A ROUTINE TO SEND A STRING TO TALKER [HL] AT STRING HIGH_SPEAK: LD A,(HL) CP '$' JR Z,SPEAK1 LD C,A CALL HIGH_SPEAKOUT INC HL JR HIGH_SPEAK SPEAK1: LD C,0DH ;MUST END WITH A CR JP HIGH_SPEAKOUT ;<<<<<<<<<<<<<<<<<<< MAIN CONSOL STATUS ROUTINE >>>>>>>>>>>>>>>>>>>>>> HIGH_CSTS: IN A,(IOBYTE) BIT 5,A ;SEE IF SERIAL PORT STATUS IS REQ JR NZ,NO_SER_STAT JP SERIAL_STAT ;Check if anything at Modem IN status routine NO_SER_STAT: IN A,(CONSOL_STATUS) AND 02H JP Z,NOCHAR XOR A DEC A ;RETURN WITH 0FFH IN [A] IF SOMETHING RET NOCHAR: XOR A ;RETURN WITH 0 IN A IF NOTHING THERE RET ;<<<<<<<<<<<<<<<<<<<< MAIN CONSOL INPUT ROUTINE >>>>>>>>>>>>>>>>>>>> HIGH_CI: IN A,(IOBYTE) BIT 5,A ;SEE IF SERIAL PORT INPUT IS REQ JR NZ,CI_IN ;NO, then do normal CI CALL SERIAL_STAT ;See if anything at Serial/Modem input JP Z,HIGH_CI ;No Keep trying JP SERIAL_IN CI_IN: IN A,(CONSOL_STATUS) ;NEED CONSTAT TO CLEAN UP SHIFT KEYS ETC AND 02H JR Z,CI_IN IN A,(CONSOL_IN) AND 7FH ;7 bits only RET ;>>>>>>>>>>>>>>>>>> S100Computers SERIAL I/O Board <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ; Note the S100Computers I/O board will have the SSC-B set initially to 19,200 Baud ; SERIAL_OUT: XOR A,A ;Will try 256 times, then timeout MODXXX: PUSH AF IN A,(ACTL) ;MODEM/SERIAL OUT AND 04H ;Are we ready for a character JR NZ,SENDM ;NZ if ready to recieve character POP AF DEC A JR NZ,MODXXX RET SENDM: POP AF LD A,C OUT (ADTA),A ;Send it RET SERIAL_IN: XOR A,A ;Will try 256 times, then timeout SERIAL_INX: PUSH AF CALL SERIAL_STAT ;MODEN/SERIAL IN JR NZ,GETMOD POP AF DEC A JR NZ,SERIAL_INX RET GETMOD: POP AF IN A,(ADTA) RET SERIAL_STAT: IN A,(ACTL) AND 01H RET Z ;Ret Z if nothing XOR A DEC A RET ;Ret FF/NZ if something ;S100Computers Serial I/O Board Initilization ;Note Zilog SCC serial port A will be set to 19,200 Baud initially (for speech synthesizer). ;Note Zilog SCC serial port B will be set to 38,400 Baud initially (for XModem etc). HIGH_INIT_SCC_A: LD A,ACTL ;Program Channel A LD C,A LD B,0EH ;Byte count for OTIR below LD HL,HIGH_SCCINIT_A OTIR RET HIGH_INIT_SCC_B: LD A,BCTL ;Program Channel B LD C,A LD B,0EH ;Byte count for OTIR below LD HL,HIGH_SCCINIT_B OTIR RET ; ; HIGH_SCCINIT_A: DB 04H ;Point to WR4 DB 44H ;X16 clock,1 Stop,NP DB 03H ;Point to WR3 DB 0C1H ;Enable reciever, Auto Enable, Recieve 8 bits ; DB 0E1H ;Enable reciever, No Auto Enable, Recieve 8 bits (for CTS bit) DB 05H ;Point to WR5 DB 0EAH ;Enable, Transmit 8 bits DB 0BH ;Set RTS,DTR, Enable. Point to WR11 DB 56H ;Recieve/transmit clock = BRG DB 0CH ;Point to WR12 ; DB 40H ;Low Byte 2400 Baud ; DB 1EH ;Low Byte 4800 Baud ; DB 0EH ;Low Byte 9600 Baud ; DB 06H ;Low byte 19,200 Baud DB 02H ;Low byte 38,400 Baud <<<<<<<<<<< XModem I/O ; DB 00H ;Low byte 76,800 Baud DB 0DH ;Point to WR13 DB 00H ;High byte for Baud DB 0EH ;Point to WR14 DB 01H ;Use 4.9152 MHz Clock. Note SD Systems uses a 2.4576 MHz clock, enable BRG DB 0FH ;Point to WR15 DB 00H ;Generate Int with CTS going high HIGH_SCCINIT_B: DB 04H ;Point to WR4 DB 44H ;X16 clock,1 Stop,NP DB 03H ;Point to WR3 DB 0C1H ;Enable reciever, Auto Enable, Recieve 8 bits DB 05H ;Point to WR5 DB 0EAH ;Enable, Transmit 8 bits DB 0BH ;Set RTS,DTR, Enable. Point to WR11 DB 56H ;Recieve/transmit clock = BRG DB 0CH ;Point to WR12 DB 06H ;Low byte 19,200 Baud <<<<<<<<<<< Note Speech synthizer defaults to this value DB 0DH ;Point to WR13 DB 00H ;High byte for Baud DB 0EH ;Point to WR14 DB 01H ;Use 4.9152 MHz Clock. Note SD Systems uses a 2.4576 MHz clock, enable BRG DB 0FH ;Point to WR15 DB 00H ;Generate Int with CTS going high ; ; ; ;---------------WE NEED A FEW ROUTINES (ALSO IN THE LOW PAGE) TO PROCESS COMMNADS-------------- ; HIGH_QCHK: ;TEST FOR DELIMITERS CP SPACE RET Z CP ',' RET Z CP CR SCF RET Z CCF RET ;KEYBOARD HANDELING ROUTINE (WILL NOT ECHO CR/LF) ;IT CONVERTS LOWER CASE TO UPPER CASE FOR LOOKUP COMMANDS ;ALSO ^C WILL FORCE A JUMP TO BOOT IN CP/M ;ALL OTHERE CHARACTERS ARE ECHOED ON CONSOL HIGH_TI: CALL HIGH_CI CP CR RET Z CP 'C'-40H ;^C TO BOOT IN CP/M JP Z,NoHighPageError PUSH BC LD C,A CALL HIGH_CO LD A,C POP BC CP 40H ;LC->UC RET C CP 7BH RET NC SF754: AND 5FH RET EXPR1: LD C,01H ;GET ONE PARAMETER HIGH_HEXSP: LD HL,0000 EX0: CALL HIGH_TI EX1: LD B,A CALL HIGH_NIBBLE JR C,EX2X ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL OR L LD L,A JR EX0 EX2X: EX (SP),HL PUSH HL LD A,B CALL HIGH_QCHK JR NC,SF560 DEC C RET Z SF560: JP NZ,HIGH_ERROR DEC C JR NZ,HIGH_HEXSP RET EXF: LD C,01H LD HL,0000H JR EX1 ;CONVERT HEX TO ASCII HIGH_CONV: AND 0FH ADD A,90H DAA ADC A,40H DAA LD C,A RET HIGH_NIBBLE: SUB 30H RET C CP 17H CCF RET C CP LF CCF RET NC SUB 07H CP LF RET HIGH_PRINT_STRING: ;A ROUTINE TO PRINT OUT A STRING @ [HL] LD A,(HL) ;UP TO THE FIRST '$'. INC HL CP '$' RET Z LD C,A CALL HIGH_CO JR HIGH_PRINT_STRING ;SEND TO CONSOL CR/LF HIGH_CRLF: PUSH BC LD C,LF CALL HIGH_CO LD C,CR CALL HIGH_CO POP BC RET ;PRINT [HL] ON CONSOL HIGH_LADR: LD A,H CALL HIGH_LBYTE LD A,L HIGH_LBYTE: HEXOUT: PUSH AF RRCA RRCA RRCA RRCA CALL SF598 POP AF SF598: CALL HIGH_CONV JP HIGH_CO HIGH_ERROR: ;RESTORE SYSTEM AFTER ERROR (Back to low page) LD C,'*' CALL HIGH_CO JP ACTIVATE_LOW_PAGE ;--------------------------------------------------------------------------------------------------------------- ;This code will read a download file from another computer (usually a PC) sent via a serial port and place ;it in RAM at a specified location. The file must be sent via the XModem protocol. On PC's there are ;many programs that do this. The "Absolute Telnet" program (by Celestial Software) is what I use. HIGH_XMODEM: LD HL,MODEM_SIGNON ;Send Modem signon message CALL HIGH_PRINT_STRING LD HL,0 ;SP to HL ADD HL,SP LD DE,40H ;Drop 40H bytes below to be safe SBC HL,DE PUSH HL POP IX ;Will store data below in RAM 40H bytes below SP to be safe XOR A,A ;Initilize flags LD (IX+RECVD_SECT_NO),A LD (IX+SECTNO),A LD (IX+ERRCT),A LD HL,MODEM_RAM_LOC ;Get RAM location for where to place code CALL HIGH_PRINT_STRING LD C,1 CALL ZHEXSP ;Get 16 bit value, put on stack POP IY ;DMA Value now in IY CALL ZCRLF CALL HIGH_INIT_SCC_A ;INITITIALIZE THE SCC SERIAL PORT A LD B,1 ;TIMEOUT DELAY CALL RECV ;GOBBLE UP GARBAGE CHARS FROM THE LINE LD HL,DOWNLOAD_SP ;Speak downloading file CALL HIGH_SPEAK RECV_LOOP: ; ---- MAIN RECIEVE LOOP ---- XOR A,A ;GET 0 LD (IX+ERRCT),A ;INITIAL ERROR COUNT SET TO 0 RECV_HDR: LD HL,RMSG CALL HIGH_PRINT_STRING LD A,(IX+SECTNO) ;Get current sector number INC A CALL HIGH_LBYTE ;Show Sector Number on Console LD HL,MODEM_RAM_MSG ;"H. IF OK, will write to RAM location" CALL HIGH_PRINT_STRING PUSH IY POP HL ;IY to HL CALL HIGH_LADR ;Show DMA Address CALL ZCRLF LD B,5 ;5 SEC TIMEOUT CALL RECV JP NC,RHNTO ;IF ALL OK (NO TIMEOUT), THEN DROP DOWN TO RHNTO TO GET DATA RECV_HDR_TIMEOUT: CALL TOUT ;PRINT TIMEOUT RECV_SECT_ERR: ;PURGE THE LINE OF INPUT CHARS LD B,1 ;1 SEC W/NO CHARS CALL RECV JP NC,RECV_SECT_ERR ;LOOP UNTIL SENDER DONE LD A,NAK CALL SEND ;SEND NAK LD A,(IX+ERRCT) INC A LD (IX+ERRCT),A CP A,MODEM_ERR_LIMIT JP C,RECV_HDR CALL CHECK_FOR_QUIT JP Z,RECV_HDR LD HL,BAD_HEADER_MSG CALL HIGH_PRINT_STRING JP EXIT RHNTO: CP A,SOH ;GOT CHAR - MUST BE SOH JP Z,GOT_SOH ;Z IF OK OR A,A ;00 FROM SPEED CHECK? JP Z,RECV_HDR CP A,EOT JP Z,GOT_EOT ;DIDN'T GET SOH - CALL HIGH_LBYTE LD HL,ERRSOH CALL HIGH_PRINT_STRING JP RECV_SECT_ERR GOT_SOH: LD B,1 CALL RECV JP C,RECV_HDR_TIMEOUT LD D,A ;D=BLK # LD B,1 CALL RECV ;GET CMA'D SECT # JP C,RECV_HDR_TIMEOUT CPL CP A,D ;GOOD SECTOR #? JP Z,RECV_SECTOR LD HL,ERR2 ;GOT BAD SECTOR # CALL HIGH_PRINT_STRING JP RECV_SECT_ERR RECV_SECTOR: ;Sector is OK, so read data and place in RAM LD A,D ;GET SECTOR # LD (IX+RECVD_SECT_NO),A LD C,0 ;INIT CKSUM LD E,80H ;Sector Byte Count PUSH IY POP HL ;DMA address (IY) to HL RECV_CHAR: LD B,1 ;1 SEC TIMEOUT CALL RECV ;GET CHAR JP C,RECV_HDR_TIMEOUT LD (HL),A ;STORE CHAR INC HL DEC E ;Next sector byte JP NZ,RECV_CHAR ;VERIFY CHECKSUM LD D,C ;SAVE CHECKSUM LD B,1 ;TIMEOUT CALL RECV ;GET CHECKSUM JP C,RECV_HDR_TIMEOUT CP A,D ;CHECK JP NZ,RECV_CKSUM_ERR ;GOT A SECTOR, WRITE IF = 1+PREV SECTOR LD A,(IX+RECVD_SECT_NO) LD B,A ;SAVE IT LD A,(IX+SECTNO) ;GET PREV INC A ;CALC NEXT SECTOR # CP B ;MATCH? JP NZ,DO_ACK LD (IX+SECTNO),A ;UPDATE SECTOR # DO_ACK: LD A,ACK CALL SEND PUSH HL ;ALL OK SO SAVE DMA Address in IY POP IY JP RECV_LOOP ;Back to Top recieve loop RECV_CKSUM_ERR: LD HL,ERR3 CALL HIGH_PRINT_STRING JP RECV_SECT_ERR GOT_EOT: LD A,ACK ;ACK THE EOT CALL SEND JP XFER_CPLT ;---------------------------------------------------- ; XMODEM SERIAL PORT GET CHARACTER ROUTINE ;---------------------------------------------------- RECV: PUSH DE ;SAVE D,E LD A,5H ;Lower RTS line OUT MODEM_CTL_PORT,A ;Sel Reg 5 LD A,11101010B ;EAH OUT MODEM_CTL_PORT,A NOP NOP MSEC: LD DE,0BBBBH ;1 SEC DCR COUNT MWTI: IN A,MODEM_CTL_PORT AND A,MODEM_RECV_MASK CP A,RECV_READY JP Z,MCHAR ;GOT CHAR DEC E ;COUNT DOWN JP NZ,MWTI ;FOR TIMEOUT DEC D JP NZ,MWTI DEC B ;DCR # OF SECONDS JP NZ,MSEC ;MODEM TIMED OUT RECEIVING POP DE ;RESTORE D,E SCF ;CARRY SHOWS TIMEOUT RET ;GOT MODEM CHAR MCHAR: IN A,MODEM_DATA_PORT POP DE ;RESTORE DE PUSH AF ;CALC CHECKSUM ADD A,C LD C,A POP AF OR A,A ;TURN OFF CARRY TO SHOW NO TIMEOUT RET ;---------------------------------------------------- ; XMODEM SERIAL PORT SEND CHARACTER ROUTINE ;---------------------------------------------------- SEND: PUSH AF ;CHECK IF MONITORING OUTPUT ADD A,C ;CALC CKSUM LD C,A SENDW: IN A,MODEM_CTL_PORT ;Don't worry PC is always fast enough! AND A,MODEM_SEND_MASK CP A,SEND_READY JP NZ,SENDW POP AF ;GET CHAR OUT MODEM_DATA_PORT,A ;Raise RTS line to prevent the next character arriving LD A,5H ;while the Z80 is busy processing info OUT MODEM_CTL_PORT,A ;Sel Reg 5 LD A,11101000B ;E8H OUT MODEM_CTL_PORT,A RET ;---------------- SUPPORT ROUTINES ----------------------------- TOUT: LD HL,TOUTM ;PRINT TIMEOUT MESSAGE CALL HIGH_PRINT_STRING LD A,(IX+ERRCT) CALL HIGH_LBYTE CALL ZCRLF RET CO_A: PUSH AF ;PRINT VALUE of [A] on CRT PUSH BC LD C,A CALL HIGH_CO POP BC POP AF RET CHECK_FOR_QUIT: ;MULTIPLE ERRORS, ASK IF TIME TO QUIT XOR A,A ;GET 0 LD (IX+ERRCT),A ;RESET ERROR COUNT LD HL,QUITM CALL HIGH_PRINT_STRING CI3: IN A,CONSOL_STATUS ;NEED CONSTAT TO CLEAN UP SHIFT KEYS ETC AND A,02H JP Z,CI3 IN A,CONSOL_IN AND A,7FH PUSH AF ;SAVE CHAR CALL ZCRLF POP AF CP A,'R' RET Z ;RETURN IF RETRY CP A,'r' RET Z CP A,'Q' ;QUIT? JP NZ,LCQ OR A,A ;TURN OFF ZERO FLAG RET LCQ: CP A,'q' JP NZ,CHECK_FOR_QUIT OR A,A ;TURN OFF ZERO FLAG RET XFER_CPLT: ;DONE - CLOSE UP SHOP LD HL,FINISH_SP ;Speak downloading finished CALL HIGH_SPEAK LD HL,MODEM_DONE_MSG CALL HIGH_PRINT_STRING EXIT: JP ZSTART ; ; ;---------------------------------------------- FPGA DC Board IDE MENU ---------------------------------- HIGH_FPGA_IDE: LD HL,IDE_SIGNON ;Send FPGA_DC Board signon message CALL HIGH_PRINT_STRING LD A,0H OUT (SOFT_RESET_PORT),A ;Reset FPGA_DC board OUT (STATUS_PORTS_RESET),A ;Reset board its status bits IN A,(S100_STATUS_PORT) ;If FPGA_DC is active this will be X000000X AND A,01111110B JR NZ,NO_RESPONSE LD C,CMD_HANDSHAKE ;21H CALL SEND_S100_TO_FPGA ;Send Handshake signal, wait until read LD HL,0 DO_HANDSHAKE1: DEC HL LD A,L OR A,H JP Z,NO_RESPONSE ;64K times, give up! CALL GET_FPGA_TO_S100 JR Z,DO_HANDSHAKE1 ;Z if no data (S100_RTS, bit 7 not high) retry again CP A,CMD_HANDSHAKE ;Send back ACK HANDSHAKE to S100 bus JR Z,GOT_HANDSHAKE NO_RESPONSE: LD HL,NO_RESPONSE_MSG ;FPGA_ DC Board is not responding CALL HIGH_PRINT_STRING JP EXIT GOT_HANDSHAKE: LD E,1 ;Start off with drive 1: LD IY,1 CALL SEL_DRIVE1 JP NZ,EXIT LD DE,0 ;Save Local Track/sec info PUSH DE POP IX ;DE->IX JP IDE_LOOP1 IDE_LOOP: LD HL,IDE_SIGNON ;Send FPGA_DC Board signon message CALL HIGH_PRINT_STRING CALL GET_DRV_TRK_SEC ;Need to update new Track Sector info and show it JP Z,EXIT IDE_LOOP1: CALL SHOW_DMA_TRK_SEC ;Display current Track,sector,head# CALL HIGH_CRLF LD C,'>' CALL HIGH_CO CALL HIGH_TI ;Simple UC character Input (Note, no fancy checking) CP A,ESC ;Abort if ESC JP Z,EXIT PUSH AF CALL ZCRLF POP AF CP A,'R' JP Z,IDE_SEC_READ CP A,'W' JP Z,IDE_SEC_WRITE CP A,'W' JP Z,IDE_SEC_WRITE CP A,'N' JP Z,IDE_NEXT_SEC CP A,'P' JP Z,IDE_PREV_SEC CP A,'S' JP Z,SET_TRK_SEC CP A,'C' JP Z,IDE_CPM_BOOT CP A,'Y' JP Z,IDE_COPY CP A,'Q' JP Z,IDE_DRIVE_SELECT CP A,'F' JP Z,IDE_FORMAT LD C,BELL CALL HIGH_CO JP HIGH_FPGA_IDE ;Bad Menu item ; ; ;-------------------------------------- SECTOR READ ----------------------------------------------------------- ; IDE_SEC_READ: LD C,CMD_SET_TRK_SEC ;31H, Send CMD_SET_TRK_SEC CALL SEND_S100_TO_FPGA PUSH IX POP DE LD C,D ;Track CALL SEND_S100_TO_FPGA LD C,E ;Note: no check data is < MAXSEC, sectors start 0,1,2,3.... CALL SEND_S100_TO_FPGA CALL GET_FPGA_TO_S100 ;Get returned signal CP A,CMD_COMPLETE ;Check CMD is Complete JP NZ,DR_TRK_SEC_ERR ;Error setting track/sector ;<<<<< SECTOR READ LOOP >>>>>>>>>>>>>>>>>> LD C,CMD_READ_SECTOR ;10H, Send CMD_READ_IDE_SECTOR command (Note. Assumes Track & Sector is ALREADY set) CALL SEND_S100_TO_FPGA LD HL,@SECTOR_BUFFER ;@SECTOR_BUFFER->HL ld b,0 ;<--- Note we assume 512 byte sectors for all IDE/CF cards (256X2 bytes) MORE_SEC_RD1: ;<<<< LOOP Sector READ >>>> CALL GET_FPGA_TO_S100 ;Get data in [A] back to S100 LD (HL),A INC HL CALL GET_FPGA_TO_S100 ;Get data in [A] back to S100 LD (HL),A INC HL DJNZ MORE_SEC_RD1 ;Get all 2X255 bytes CALL GET_FPGA_TO_S100 ;Get returned signal CP A,CMD_FAILED ;Check CMD is OK JR Z,SEC_RD_ERR1 CP A,CMD_COMPLETE ;Check CMD is Complete JR NZ,CMD_COMPLETE_ERR LD HL,@SECTOR_BUFFER ;@SECTOR_BUFFER->HL CALL HIGH_CRLF CALL SEC_DUMP ;Show contents of RAM at SECTOR_BUFFER (Registers changed) CALL SHOW_DMA_TRK_SEC ;Display current Track,sector,head# CALL HIGH_CRLF LD HL,CONTINUE_MSG ;Any keyboard character for next sector. Esc to Main Menu CALL HIGH_PRINT_STRING CALL HIGH_CI CP A,ESC JP Z,IDE_LOOP CALL SEC_BUMP ;Point to next sector. Note this updates LBA also JP IDE_SEC_READ ;Read another sector ; ; SEC_RD_ERR1: LD DE,SEC_RD_ERR1_MSG ;Sect RD Error (RAM) CALL HIGH_PRINT_STRING JP IDE_LOOP CMD_COMPLETE_ERR: LD DE,SEC_RD_ERR2_MSG ;'No CMD_COMPLETE Error$' CALL HIGH_PRINT_STRING JP IDE_LOOP ; ; ;---------------------------------- SECTOR WRITE --------------------------------------------------------- ; IDE_SEC_WRITE: LD C,CMD_SET_TRK_SEC ;31H, Send CMD_SET_TRK_SEC CALL SEND_S100_TO_FPGA PUSH IX POP DE LD C,D ;Track CALL SEND_S100_TO_FPGA LD C,E ;Note: no check data is < MAXSEC, sectors start 0,1,2,3.... CALL SEND_S100_TO_FPGA CALL GET_FPGA_TO_S100 ;Get returned signal CP A,CMD_COMPLETE ;Check CMD is Complete JP NZ,DR_TRK_SEC_ERR ;Error setting track/sector ;<<<<< SECTOR WRITE LOOP >>>>>>>>>>>>>>>>>> LD C,CMD_WRITE_SECTOR ;10H, Send CMD_READ_IDE_SECTOR command (Note. Assumes Track & Sector is ALREADY set) CALL SEND_S100_TO_FPGA LD HL,@SECTOR_BUFFER ;@SECTOR_BUFFER->HL ld b,0 ;<--- Note we assume 512 byte sectors for all IDE/CF cards (256X2 bytes) MORE_SEC_WR1: ;<<<< LOOP Sector WRITE >>>> LD C,(HL) CALL SEND_S100_TO_FPGA ;Get data in [A] back to S100 INC HL LD C,(HL) CALL SEND_S100_TO_FPGA ;Get data in [A] back to S100 INC HL DJNZ MORE_SEC_WR1 ;Get all 2X255 bytes CALL GET_FPGA_TO_S100 ;Get returned signal CP A,CMD_FAILED ;Check CMD is OK JR Z,SEC_WR_ERR1 CP A,CMD_COMPLETE ;Check CMD is Complete JR NZ,CMD_COMPLETE_ERR LD HL,@SECTOR_BUFFER ;@SECTOR_BUFFER->HL CALL HIGH_CRLF CALL SEC_DUMP ;Show contents of RAM at SECTOR_BUFFER (Registers changed) CALL SHOW_DMA_TRK_SEC ;Display current Track,sector,head# CALL HIGH_CRLF LD HL,CONTINUE_MSG ;Any keyboard character for next sector. Esc to Main Menu CALL HIGH_PRINT_STRING CALL HIGH_CI CP A,ESC JP Z,IDE_LOOP CALL SEC_BUMP ;Point to next sector. Note this updates LBA also JP IDE_SEC_WRITE ;Read another sector ; ; SEC_WR_ERR1: LD DE,SEC_WRD_ERR1_MSG ;Sect RD Error (RAM) CALL HIGH_PRINT_STRING JP IDE_LOOP ;---------------------------------- SET TRACK & SECTOR --------------------------------------------------------- SET_TRK_SEC: ;Keyboard entry of new IDE drive track/sector data FORMAT:- (XX,XX+CR) LD HL,ENTER_TS_DATA CALL HIGH_PRINT_STRING CALL GET_DIGIT JP C,ABORT_SET_TRK_SEC PUSH IX POP DE LD D,A PUSH DE POP IX LD C,',' CALL HIGH_CO CALL GET_DIGIT JP C,ABORT_SET_TRK_SEC PUSH IX POP DE LD E,A PUSH DE POP IX LD C,CMD_SET_TRK_SEC ;31H, Now update board, Send CMD_SET_TRK_SEC CALL SEND_S100_TO_FPGA PUSH IX POP DE LD C,D ;Track CALL SEND_S100_TO_FPGA LD C,E ;Note: no check data is < MAXSEC, sectors start 0,1,2,3.... CALL SEND_S100_TO_FPGA CALL GET_FPGA_TO_S100 ;Get returned signal CP A,CMD_COMPLETE ;Check CMD is Complete JP NZ,DR_TRK_SEC_ERR ;Error setting track/sector ABORT_SET_TRK_SEC: JP IDE_LOOP ;---------------------------------- POINTS TO PREVIOUS SECTOR --------------------------------------------------- IDE_PREV_SEC: LD C,CMD_BACK_SEC ;37H, Send CMD to point to the previoust sector CALL SEND_S100_TO_FPGA CALL GET_FPGA_TO_S100 ;Get returned ACK signal CP A,CMD_COMPLETE ;Check CMD is Complete JP NZ,CMD_COMPLETE_ERR CALL GET_DRV_TRK_SEC JP IDE_LOOP ; ; ;---------------------------------- POINTS TO NEXT SECTOR --------------------------------------------------------- IDE_NEXT_SEC: ;Generalized routine to point to the next sector/track LD C,CMD_BUMP_SEC ;36H, Send CMD to point to the next sector CALL SEND_S100_TO_FPGA CALL GET_FPGA_TO_S100 ;Get returned ACK signal CP A,CMD_COMPLETE ;Check CMD is Complete JP NZ,CMD_COMPLETE_ERR CALL GET_DRV_TRK_SEC JP IDE_LOOP ; ; ;---------------------------------- COPY 1:->2: --------------------------------------------------------- IDE_COPY: LD HL,COPY_DR1_MSG ;'Will copy 1:->2: How many tracks (0-FFH) $ call HIGH_PRINT_STRING CALL GET_DIGIT JP C,IDE_LOOP PUSH AF ;Save it # of tracks to copy (Use > 20 for CPM3) LD E,1 ;Force first drive to be 1: LD IY,1 CALL SEL_DRIVE1 JP NZ,COPY_ERROR LD HL,COPYING_MSG ;Will copy current complete drive to another. call HIGH_PRINT_STRING LD C,CMD_DRIVE_COPY ;3CH, Copy Drives CALL SEND_S100_TO_FPGA LD A,2 LD C,A ;Send second drive letter CALL SEND_S100_TO_FPGA POP AF LD C,A ;Send track count CALL SEND_S100_TO_FPGA CALL GET_FPGA_TO_S100 ;Get returned signal termination signal CP A,CMD_COMPLETE ;Check CMD is Complete JR NZ,COPY_ERROR LD HL,DISK_COPY_OK_MSG ;Multi sector(s) writing complete JR DONE_COPY COPY_ERROR: LD HL,COPY_ERR_MSG ;Drive copy failed to complete properly DONE_COPY: CALL HIGH_PRINT_STRING JP HIGH_FPGA_IDE ;Cleanup everything! ; ; ; ;---------------------------------- BOOT CPM --------------------------------------------------------- IDE_CPM_BOOT: LD HL,WILL_LOAD_CPM_MSG CALL HIGH_PRINT_STRING LD C,CMD_SET_TRK_SEC ;31H, Send CMD_SET_TRK_SEC CALL SEND_S100_TO_FPGA LD C,0 ;Track CALL SEND_S100_TO_FPGA LD C,1 ;Note: no check data is < MAXSEC, sectors start 0,1,2,3.... CALL SEND_S100_TO_FPGA CALL GET_FPGA_TO_S100 ;Get returned signal CP A,CMD_COMPLETE ;Check CMD is Complete JP NZ,DR_TRK_SEC_ERR LD C,CMD_CPM_BOOT ;3BH, Load CPM Image CALL SEND_S100_TO_FPGA LD C,CPM_SEC_COUNT ;Send sector count to FPGA_DC Board CALL SEND_S100_TO_FPGA LD HL,CPMLDR_ADDRESS ;Get RAM location for data (100H) LD B,0 ;<--- Note we assume 512 byte sectors for all IDE/CF cards (256X2 bytes) LD A,CPM_SEC_COUNT ;sector count of sectors to read PUSH AF ;Save them BOOT_N3: ;<<<< LOOP N Sector READ >>>> BOOT_N2: ;<<<< LOOP 1 Sector READ >>>> CALL GET_FPGA_TO_S100 ;Get data in [A] back to S100 LD (HL),A INC HL CALL GET_FPGA_TO_S100 ;Get data in [A] back to S100 LD (HL),A INC HL DJNZ BOOT_N2 ;Send all 2X255 bytes POP AF ;Count down sectors to read DEC A JR Z,BOOT_N4 PUSH AF LD C,'.' ;Show progress CALL HIGH_CO CALL SEC_BUMP ;Need to update locally as well LD B,0 ;Just in case JR BOOT_N3 BOOT_N4: CALL GET_FPGA_TO_S100 ;Get returned signal termination signal CP A,CMD_COMPLETE ;Check CMD is Complete JP Z,CPMLDR_ADDRESS ;CONTROL NOW WITH CPM ; JP 0F000H ;For debugging BOOT_RD_ERR: LD HL,BOOT_ERR_MSG ;Error loading CPM from current drive CALL HIGH_PRINT_STRING JP IDE_LOOP ; ; ;--------------------------------------- SELECT DRIVE ------------------------------------------ IDE_DRIVE_SELECT: CALL SELECT_CURRENT_DRIVE ;New drive in IY JP IDE_LOOP ; ; ;--------------------------------------- FORMAT DISK ------------------------------------------ IDE_FORMAT: ;Format Current disk LD HL,FORMAT_N_MSG ;How many tracks to Format (Usually 02H):- call HIGH_PRINT_STRING CALL GET_DIGIT JP C,IDE_LOOP PUSH AF ;Save it # of tracks to copy (Use > 20 for CPM3) LD HL,FORMAT_STARTED_MSG ;Format started call HIGH_PRINT_STRING LD C,CMD_FORMAT_DISK ;40H, Format the CURRENT DISK CALL SEND_S100_TO_FPGA POP AF ;Get track count LD C,A CALL SEND_S100_TO_FPGA CALL GET_FPGA_TO_S100 ;Get returned signal CP A,CMD_COMPLETE ;Check CMD is Complete JR NZ,FORMAT_ERROR LD HL,FORMAT_DONE_MSG ;Drive format done JR FORMAT_DONE FORMAT_ERROR: LD HL,FORMAT_ERR_MSG ;Drive format failed FORMAT_DONE: CALL HIGH_PRINT_STRING JP HIGH_FPGA_IDE ;Cleanup everything! ; ; ; ;----------------------------------------------------------------------------------------------- ;--------------------------------------- IDE SUPPORT ROUTINES ---------------------------------- ;----------------------------------------------------------------------------------------------- ; SELECT_CURRENT_DRIVE: ;IY=CURRENT DRIVE LD HL,CURRENT_DR_MSG CALL HIGH_PRINT_STRING CALL HIGH_CI LD C,A CALL HIGH_CO CP A,'1' LD E,1 JR Z,SEL_DRIVE CP A,'2' LD E,2 JR Z,SEL_DRIVE JR BAD_DRIVE SEL_DRIVE: ;Arrive here with selecetd drive in [E] PUSH DE LD HL,SELECTING_DR_MSG CALL HIGH_PRINT_STRING POP DE LD A,E CALL HEXOUT LD HL,SELECTING1_DR_MSG CALL HIGH_PRINT_STRING SEL_DRIVE1: LD D,0 PUSH DE POP IY ;>>>>> Drive select in IY <<<<< LD C,CMD_SEL_DRIVE ;05H, Select Drive CMD CALL SEND_S100_TO_FPGA LD C,E ;Always Selected drive 1: or 2: CALL SEND_S100_TO_FPGA CALL GET_FPGA_TO_S100 ;Wait for returned ACK signal CP A,CMD_COMPLETE ;Check CMD is Complete JR Z,IDE_OK BAD_DRIVE: LD HL,BAD_SEL_DR_MSG ;Error selecting a new drive CALL HIGH_PRINT_STRING XOR A,A DEC A RET ;RET NZ if a problem IDE_OK: LD C,CMD_INIT_DRIVE ;30H, Sending CMD to select and initilize the current Drive CALL SEND_S100_TO_FPGA PUSH IY ;Get drive POP DE LD C,E ;Send select drive slave address for drive (1,2) CALL SEND_S100_TO_FPGA CALL GET_FPGA_TO_S100 ;Get returned signal CP A,CMD_COMPLETE ;Check CMD is Complete RET Z ;RET Z if all OK LD HL,BAD_INIT_DR_MSG ;Error selecting a new drive CALL HIGH_PRINT_STRING XOR A,A DEC A RET ;RET NZ if a problem ;---------------------------------------- GET_DRV_TRK_SEC: LD C,CMD_GET_DRV_TRK_SEC ;32H, Send GET_DRV_TRK_SEC command CALL SEND_S100_TO_FPGA CALL GET_FPGA_TO_S100 ;Get drive letter in [A] back from FPGA_DC Board JR Z,DR_TRK_SEC_ERR CALL GET_FPGA_TO_S100 ;Get TRK data in [A] back to S100 LD D,A ;Store in D CALL GET_FPGA_TO_S100 ;Get SEC data in [A] back to S100 LD E,A ;Store in E PUSH DE POP IX ;Trk & Sec now in IX CALL GET_FPGA_TO_S100 ;Get returned signal CP A,CMD_COMPLETE ;Check CMD is Complete JR NZ,DR_TRK_SEC_ERR XOR A,A INC A RET ;NZ if all OK DR_TRK_SEC_ERR: LD HL,TRK_SEC_ERR_MSG ;'Drive/Track/Sector Error$' CALL HIGH_PRINT_STRING XOR A,A RET ;Z if error ; ; ;---------------------------------------- GET_DIGIT: PUSH BC CALL HIGH_CI CP A,CR JP Z,DATA_ENTRY_ABORT ;IF CR THEN ABORT CP ESC JP Z,DATA_ENTRY_ABORT ;IF ESC THEN ABORT CALL UCASE cp A,'/' ;check 0-9, A-F jp c,DATA_ENTRY_ABORT cp A,'F'+1 jp nc,DATA_ENTRY_ABORT LD E,A LD C,A CALL HIGH_CO LD A,E call ASBIN ;Convert to binary rlca ;Shift to high nibble rlca rlca rlca LD B,A ;Store it CALL HIGH_CI CP A,CR JP Z,DATA_ENTRY_ABORT ;IF CR THEN ABORT CP ESC JP Z,DATA_ENTRY_ABORT ;IF ESC THEN ABORT CALL UCASE cp A,'/' ;check 0-9, A-F jp c,DATA_ENTRY_ABORT cp A,'F'+1 jp nc,DATA_ENTRY_ABORT LD E,A LD C,A CALL HIGH_CO LD A,E call ASBIN ;Convert to binary or B ;add in the first digit OR A ;Clear CF POP BC RET DATA_ENTRY_ABORT: POP BC SCF ;Set CF RET ; ; ASCII TO BINARY CONVERSION ROUTINE ASBIN: SUB 30H CP 0AH RET M SUB 07H RET ; ;Convert LC to UC UCASE: CP A,'a' ;must be >= lowercase a RET C ; else go back... CP A,'z'+1 ;must be <= lowercase z RET NC ; else go back... SUB A,'a'-'A' ;subtract lowercase bias RET ;------------------------------------------- SHOW_DMA_TRK_SEC: LD HL,DMA_MSG CALL HIGH_PRINT_STRING LD HL,@SECTOR_BUFFER ;@SECTOR_BUFFER->HL CALL HIGH_LADR LD HL,DRIVE_MSG CALL HIGH_PRINT_STRING PUSH IY POP DE LD A,E ;Get Drive CALL HEXOUT LD HL,TRK_SEC_MSG CALL HIGH_PRINT_STRING PUSH IX POP DE LD A,D ;Get track CALL HEXOUT LD HL,TRK_SEC1_MSG CALL HIGH_PRINT_STRING PUSH IX POP DE LD A,E ;Get Sector CALL HEXOUT LD HL,HCRLF_MSG CALL HIGH_PRINT_STRING RET ;-------------------------------------------- SEC_BUMP: ;Generalized routine to point to the next sector/track PUSH BC PUSH DE LD C,NSCTRS ;Is it the last sector on track PUSH IX POP DE ;D = TRACK, E = SECTOR LD A,E ;<<< NOTE CURRENTLY LIMITED TO 0FFH SECTORS/TRACK >>> CP A,C JR Z,SEC_BUMP_TRK INC A LD E,A PUSH DE POP IX ;New Trk/SEC back in IX POP DE POP BC RET SEC_BUMP_TRK: LD E,0 ;SEC back to 0 LD A,D INC A CP A,0 ;Last track JR Z,AT_END ;RET Z if at end LD D,A ;New track back in D AT_END: PUSH DE POP IX ;New Track and Sectior in IX POP DE POP BC RET ; ; ;------------------------------------------ SEC_DUMP: ;Print a SEC_DUMP of the data in the 512 byte buffer @[HL] LD DE,512 ;Note code assumes address is XX00H (LOW byte,HIGH byte) LD HL,@SECTOR_BUFFER ;@SECTOR_BUFFER->HL ADD HL,DE PUSH HL POP DE ;DE = SECTOR BUFFER + SEC SIZE DEC DE LD HL,@SECTOR_BUFFER ;@SECTOR_BUFFER->HL LD A,L ;ROUND OFF ADDRESSES TO XXX0H AND 0F0H LD L,A LD A,E ;FINAL ADDRESS LOWER HALF AND 0F0H ADD A,10H ;FINISH TO END 0F LINE SF172A: CALL LF_PRINT_HL ;Do LF + Print value in [HL] SF175A: CALL BLANK LD A,(HL) CALL HEXOUT CALL HILO ;<--- Set C flag when HL=DE JP C,FINAL_ASCII LD A,L AND 0FH JR NZ,SF175A LD C,TAB ;INSERT A TAB BETWEEN DATA CALL ZCO LD B,4H ;ALSO 1 SPACE TA11: LD C,SPACE CALL HIGH_CO DJNZ TA11 CALL SHOW_ASCII JR SF172A SHOW_ASCII: LD B,16 ;NOW PRINT ASCII (16 CHARACTERS) PUSH DE ;TEMPORLY SAVE [DE] LD DE,0010H SBC HL,DE POP DE T11: LD A,(HL) AND 7FH CP ' ' ;FILTER OUT CONTROL CHARACTERS' JR NC,T33 T22: LD A,'.' T33: CP 07CH JR NC,T22 LD C,A ;SET UP TO SEND CALL HIGH_CO INC HL DJNZ T11 ;REPEAT FOR WHOLE LINE RET FINAL_ASCII: ;Special case to show final ASCII line LD C,TAB ;INSERT A TAB BETWEEN DATA CALL HIGH_CO LD B,4H ;ALSO 1 SPACE TA11A: LD C,SPACE CALL HIGH_CO DJNZ TA11A CALL SHOW_ASCII RET ; ; HILO: INC HL ;>>>>>>>>>>>> RANGE CHECK SET CARRY IF [DE]=[HL] LD A,H OR L SCF RET Z LD A,E SUB L LD A,D SBC A,H RET ; LF_PRINT_HL: CALL HIGH_CRLF ; ;>>>>>>>>>>>>PRINT [HL] AND A SPACE SP_PRINT_HL: PUSH HL PUSH BC CALL HIGH_LADR LD C,SPACE CALL HIGH_CO POP BC POP HL RET ; ; BLANK: LD C,SPACE CALL HIGH_CO RET ;---------------------------------------------------------------------------- ; CORE INTERFACE BETWEEN S100 BUS and FPGA_DC BOARD ; The only hardware port links for the above FPGA_DC board. ;---------------------------------------------------------------------------- ; ; GET_FPGA_TO_S100: ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< IN A,(S100_STATUS_PORT) ;Get S100 Status Port - Bit 7, 1 = S100 old data STILL present, 0, no data sent AND A,S100_RTS ;80H, Bit 7 JR NZ,GET_FPGA_TO_S100 ;wait for data to be accepted GET_FPGA1_TO_S100 IN A,(S100_STATUS_PORT) ;Get S100 Status Port - Bit 0, 1 = FPGA data present, 0, no data present AND A,FPGA_RTS ;01H, Bit 0 JR Z,GET_FPGA1_TO_S100 ;wait for DC Board to present data IN A,(S100_DATA_PORT) ;Return Data in [A], FPGA "hardware" will lower bit 7 of S100 Bus port 80H OR A,A ;Ret NZ if data RET SEND_S100_TO_FPGA: ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< PUSH HL LD HL,0 SEND2_S100_TO_FPGA: IN A,(S100_STATUS_PORT) ;Has previous data been read by FPGA AND A,S100_RTS ;80H, Has bit 7 returned low by a FPGA read JR Z,SEND1_S100_TO_FPGA DEC HL LD A,L OR A,H JR NZ,SEND2_S100_TO_FPGA XOR A DEC A ;RET NZ for error POP HL RET SEND1_S100_TO_FPGA: LD A,C OUT (S100_DATA_PORT),A ;This will set S100_RTS bit LD HL,0 SEND_S1003: IN A,(S100_STATUS_PORT) ;Wait until accepted by FPGA, this will (in hardware) lower bit 0 of status port AND A,S100_RTS ;80H, Has bit 7 returned low yet by a FPGA read JR Z,SEND_S1002 DEC HL LD A,L OR A,H JR NZ,SEND_S1003 DEC A ;RET NZ for error POP HL RET SEND_S1002: XOR A ;Ret Z no error POP HL RET ; ; ;--------------------------------------------------------------------------------------------------------------- MODEM_SIGNON: DB CR,LF,'Get a File from a PC',CR,LF DB 'Zilog SCC Ports A1H & A3H. Requires RTS & CTS, 38,400 Baud.',CR,LF,'$' MODEM_SCC_MSG: DB 'SCC Port A to 38,400 Baud.',CR,LF,'$' RMSG: DB 'WAITING FOR SECTOR #$' ERRSOH: DB 'H RECEIVED, NOT SOH',0DH,0AH,'$' ERR2: DB '++BAD SECTOR # IN HDR',0DH,0AH,'$' ERR3: DB '++BAD CKSUM ON SECTOR',0DH,0AH,'$' TOUTM: DB 'TIMEOUT $' QUITM: DB 0DH,0AH,'MULTIPLE ERRORS.' DB 0DH,0AH,'TYPE Q TO QUIT, R TO RETRY:$' MODEM_DONE_MSG: DB 13,10,'TRANSFER COMPLETE$' BAD_HEADER_MSG: DB CR,LF,'INVALID HEADER.',0DH,0AH,'$' MODEM_RAM_MSG: DB 'H. If OK will write to RAM at $' DOWNLOAD_SP: DB 'Downloading file Started.$' FINISH_SP: DB 'Down loading of file complete. No Errors$' MODEM_RAM_LOC: DB CR,LF,'Enter RAM location (xxxxH +CR): $' M_ERROR_MSG: DB 'Menu Error'CR,LF,BELL,'$' NoHighPageMsg: DB 'No ROM HigH Page!',CR,LF,BELL,'$' INVALID_PARM_MSG: DB CR,LF,'Invalid paramater passed to HIGH Page ROM',CR,LF,BELL,'$' IDE_SIGNON: DB CR,LF,LF,'FPGA_DC Board MENU',CR,LF DB 'R=Read Sec W=Write Sec N=Next Sec P=Previous Sec',CR,LF DB 'S=Set Trk&Sec Y=Copy A:->B: C=Boot CPM Q=Select Drive',CR,LF, DB 'F=Format Disk (ESC) Main Monitor',CR,LF,'$' NO_RESPONSE_MSG DB CR,LF,BELL,'FPGA_DC Board Timeout$' BAD_SEL_DR_MSG DB CR,LF,BELL,'Select Drive Error$' BAD_INIT_DR_MSG DB CR,LF,BELL,'Drive Init. Error$' TRK_SEC_ERR_MSG DB CR,LF,BELL,'Drive/Track/Sector Error$' DMA_MSG DB CR,LF,'DMA = $' DRIVE_MSG DB 'H Drive = $' TRK_SEC_MSG DB ': Track = $' TRK_SEC1_MSG DB 'H Sector = $' HCRLF_MSG DB 'H',CR,LF,'$' SEC_RD_ERR1_MSG DB CR,LF,BELL,'Sect RD Error (RAM)$' SEC_RD_ERR2_MSG DB CR,LF,BELL,'No CMD_COMPLETE Error$' CONTINUE_MSG DB CR,LF,'Any character for next Sec. Esc to abort$' ENTER_TS_DATA DB CR,LF,'Enter Track,Sec data (XXH,XXH) $' SEC_WRD_ERR1_MSG DB CR,LF,BELL,'Sect WR Error (RAM)$' BOOT_ERR_MSG DB CR,LF,BELL,'Error loading CPM$' WILL_LOAD_CPM_MSG DB CR,LF,'Will load CPM to RAM at 100H and JMP to 100H$' COPY_DR1_MSG DB CR,LF,'Will copy 1:->2: How many tracks (0-FFH) $' COPY_ERR_MSG DB CR,LF,BELL,'Disk Copy failed$' DISK_COPY_OK_MSG DB CR,LF,'Disk Copy complete',CR,LF,'$' COPYING_MSG DB CR,LF,'Copying 1:->2:$',CR,LF CURRENT_DR_MSG DB CR,LF,'Select IDE Drive 1: or 2: (1,2) $' SELECTING_DR_MSG DB CR,LF,'Selecting Drive $' SELECTING1_DR_MSG DB ':',CR,LF,'$' FORMAT_N_MSG DB CR,LF,'How many tracks to Format (Usually 02H):- $' FORMAT_STARTED_MSG DB CR,LF,'Format Started$' FORMAT_ERR_MSG DB CR,LF,BELL,'Drive Format failed$' FORMAT_DONE_MSG DB CR,LF,BELL,'Format Complete',CR,LF,'$' END_OF_ROM_PAGE: DB ' End of ROM HIGH PAGE-->' ;END