.xlist INCLUDE MON.180 .list ;***************************************************************************** ;* * ;* PROGRAM TO CONTROL THE TRACK POSITION, ETC. OF 5 1/4 INCH * ;* FLOPPY DRIVES TO MAKE HEAD ALIGNMENT POSSIBLE. * ;* BY RONALD E. JACOBS * ;* NOVEMBER 1, 1983 * ;* * ;* 05/22/86 added microdecision drive control capabilities * ;* latest work done 03/02/89 * ;* 02/10/88 Modified for use with MDMON monitor rom chip * ;* * ;***************************************************************************** if alignment ;ASSEMBLE ALIGNMENT CODE? ;************************************************************************ ;* * ;* the following is a user setable equate * ;* * ;************************************************************************ diradfg equ 8 ;0 for ADM20; 8 for ADM31 cursor addressing stack equ 4100h ;stack space and RAM use begins here cr equ 0Dh ;carriage return lf equ 0Ah ;line feed bs equ 08h ;backspace align: ld sp,stack ;starting address of stack ;**************************************************************** ;* * ;* ROUTINE DISPLA * ;* * ;* SCROLLS WHATEVER IS ON THE SCREEN OFF AND DISPLAYS * ;* THE COMMANDS AND OTHER INFORMATION ON THE SCREEN. * ;* * ;**************************************************************** ld hl,mv2ram ;source of bytes to move from ROM to RAM ld de,stack ;destination of bytes to put into RAM ld bc,endmv2-mv2ram ;number of bytes to move ldir ;move bytes into RAM displa: ld B,25 ;number of times to send Line Feed call lnfeeds ;send line feed characters to screen ld de,screen ;start addr of string call outstr ;print the string ld b,14d ;prepare for lnfeeds: b=number of line feeds call lnfeeds ;send line feed characters to screen call cylstr ;print the maximum track number after MAX TRK call denstr ;print "FM" or "MFM" after DENSITY call trkstr ;print the track number after TRACK call sidstr ;print "0" or "1" after SIDE call secstr ;print sector number after seCtor call motstr ;print "OFF" or "ON" after MOTOR call drvstr ;print the drive number (0 to 4) after DRIVE comand: ld bc,4725h ;B=column address w/offset,C=row addr w/offset call curadd ;move cursor to 'ST3' ld a,(st3) ;get status register 3 from memory ld ix,st3done jp lbyte ;convert the a register to ascii and print st3done:ld a,(bufchr) ;0 if chars not from buffer, else char. number ld bc,2829h ;B=column address w/offset,C=row addr w/offset add a,b ;move column address to current buffer charactr ld b,a ;store column address in BC for call to curadd call curadd ;move cursor to 'Command:' call inchr ;get character from keyboard or buffer ;**************************************************************** ;* * ;* SEE IF CHARACTER JUST RECEIVED FROM CONSOLE WAS * ;* A DIGIT. IF SO, CHECK FOR A SECOND DIGIT. * ;* IF NOT CHECK TO SEE IF CHARACTER IS A VALID LETTER. * ;* * ;**************************************************************** ld h,a ;save character that was typed at console ld a,(maxtrh) ;get maximum track number high digit in ASCII ld b,a ;B=max track number high digit inc b ;B=max track number high digit+1 ld a,h ;retrieve character that was typed at console cp '0' jp c,whatchr ;if typed character < 0 cp b ;b=high digit+1 of maximum track number jp c,track ;if typed character < max. high track digit+1 ;**************************************************************** ;* * ;* DETERMINE IF A VALID LETTER COMMAND WAS TYPED * ;* AND TAKE APPROPRIATE ACTION * ;* * ;**************************************************************** whatchr:CP 03h ;03h= ^C JP Z,EXIT CP 06h ;06h= ^F jp z,format cp 14h ;14h= ^T jp z,maxtrk cp ';' jp z,filbuf cp '/' jp z,setbuf and 0DFh ;convert character to upper case cp 'A' jp z,currev cp 'C' jp z,setsec ;set sector number cp 'D' jp z,data cp 'F' jp z,density cp 'H' jp z,header cp 'I' jp z,stepi cp 'O' jp z,stepo cp 'R' jp z,recal cp 'S' jp z,sidsel cp 'M' jp z,motor cp 'L' jp z,seldrv cp 'Z' jp z,sleep jp comand ;character typed wasn't valid command ;************************************************************************ ;* * ;* FILBUF ROUTINE * ;* * ;* Fill the buffer for batch execution of commands. * ;* When calling inchr the character will be returned from the * ;* console when bufcnt (memory location) is zero. * ;* * ;************************************************************************ filbuf: ld de,bscolon ;2 character string:backspace and colon call outstr ;send the string to the CRT ld hl,cmdbuf ;start of command buffer ld (bufptr),hl ;reset command buffer pointer to start ld e,0 ;buffer character count loadbuf:push hl ;store pointer to last character in buffer push de ;save buffer count call inchr ;get a character from the keyboard call outchra ;send the character from the kbd to the crt pop de ;retrieve buffer count pop hl ;retrieve pointer to last character in buffer cp cr ;is it a carriage return? jp z,fildone ;if it was a carriage return ld (hl),a ;store character into buffer inc hl ;point to next storage location in buffer inc e ;increment count of characters in buffer jr loadbuf ;get another character from the console fildone:ld a,e LD (BUFTOT),A ;TOTAL COUNT OF CHARACTERS IN BUFFER(STAYS SAME INC A ;COUNT IS PREDECREMENTED IN SUBROUTINE INCHR: ld (bufcnt),a ;store total of characters in buffer to memory xor a ;zero register A ld (bufchr),a ;store number of characters gotten from buffer ld bc,2829h ;B=column address w/offset,C=row addr w/offset call curadd ;move cursor to 'Command:' jp comand ;************************************************************************ ;* * ;* SETBUF ROUTINE * ;* * ;* Enter this routine when '/' is read from the batch command * ;* buffer. (Also entered if '/' is read from the keyboard, but * ;* in that case it won't have any effect apparent to the user.) * ;* 1. Set the buffer count to 0FFh. (Correct value in buffer * ;* count is not important since the '/' makes an endless loop.) * ;* 2. Reset the buffer pointer to start of buffer. * ;* * ;************************************************************************ setbuf: ld a,(buftot) ;maximum count of characters possible in buffer INC A ;COUNT IS PREDECREMENTED IN SUBROUTINE INCHR: ld (bufcnt),a ;store buffer count in memory xor a ;zero register A to reset number gotten ld (bufchr),a ;store number of characters gotten from buffer ld hl,cmdbuf ;start of command buffer ld (bufptr),hl ;store pointer in memory ld bc,2829h ;B=column address w/offset,C=row addr w/offset call curadd ;move cursor to 'Command:' jp comand ;************************************************************************ ;* * ;* CURREV ROUTINE * ;* * ;* TOGGLES A FLAG bit in register E which THE CURSOR ADDRESSING * ;* ROUTINE USES TO REVERSE OR NOT REVERSE THE ORDER * ;* OF TRANSMISSION OF ROW AND COLUMN TO THE TERMINAL. * ;* * ;************************************************************************ currev: ld a,(curflg) ;will be 0000$0000 or 0000$1000h xor 00001000b ;cursor addressing flag is coded into bit 3 ld (curflg),a ;store in memory jp displa ;repaint the screen then fall thru to comand ;**************************************************************** ;* * ;* EXIT ROUTINE * ;* * ;* 1. MOVE CURSOR TO SCREEN BOTTOM LEFT * ;* 2. RETURN TO MONITOR if there or warm boot if not. * ;* * ;**************************************************************** exit: ld bc,2029h ;b=column address w/offset,c=row addr w/offset call curadd ;position the cursor for exit if monitor jp (iy) ;jump to monitor program (iy loaded by monstep) else jp 0 ;warmboot endif ;**************************************************************** ;* * ;* MOTOR ROUTINE * ;* * ;**************************************************************** motor: ld a,(motogl) ;motor toggle flag cpl ;toggle motor flag between 00 and FFh ld (motogl),a ;store the toggled flag call motstr jp comand motstr: ld bc,2B27h ;B=COLUMN ADDRESS W/OFFSET,C=ROW ADDR W/OFFSET call curadd ;CURSOR ADDRESS SUBROUTINE ld a,(motogl) ;MOTOR TOGGLE FLAG or a ;0=MOTOR OFF FF=MOTOR ON ld de,offmsg ;START OF OFF MESSAGE STRING jr z,chgmot ld de,onmsg ;START OF ON MESSAGE STRING chgmot: call outstr ;print the string ret ;**************************************************************** ;* * ;* RECAL ROUTINE * ;* * ;* RECALIBRATE THE MICRODECISION CONTROLLED DRIVE BY: * ;* 1. GIVING THE NEC 765 RECALIBRATE COMMAND (WHICH * ;* STEPS OUT A MAXIMUM OF 77 TRACKS UNTIL THE * ;* TRACK 0 LINE GOES TRUE. * ;* 2. TERMINATE THE COMMAND BY GIVING THE NEC 765 * ;* SENSE INTERRUPT STATUS COMMAND. * ;* * ;**************************************************************** recal: call cmdnew ;is data port ready to receive new command? ld a,07h ;NEC 765 recalibrate command code out (0FBh),a ;send recalibrate command to NEC 765 data port call cmdrdy ;is data port ready to receive a command byte? ld a,(motdrv) ;bits 0 (=US0) and 1 (=US1) select the drive out (0FBh),a ;send second command byte to NEC 765 data port im0 ei halt ;wait for an interrupt from FDC call sensint ;perform NEC 765 sense interrupt status command call pcn ;get pointer to present drive's PCN in hl ld a,(hl) ;present drive's present track number call mkasci ;convert the hex track number to ascii chars call trkstr ;print the new track number on crt jp comand ;**************************************************************** ;* * ;* SELDRV ROUTINE * ;* * ;**************************************************************** seldrv: ld bc,2B28h ;B=column address w/offset,C=row addr w/offset call curadd ;move cursor to drive number position drvchr: call inchr ;get actual drive number from terminal ld e,a ;save a copy of the character in E and 11111100b ;valid character is 0-3; mask last 2 bits cp '0' ;is remaining character a '0' ? jr nz,drvchr ;character wasn't valid; try again selpnt: ld a,e ;get a copy of the character and 00001111b ;convert ASCII digit to binary ld (motdrv),a ;store drive number call outchre ;print the character that is in register E ;*TEST FOR MICRODECISION DRIVES WHICH HAVE NEVER BEEN CALIBRATED BY FSTEP call motrun ;so hardware selects the new drive call pcn ;get pointer to present drive's PCN in hl ld a,(hl) ;present drive's present track number cp 0FFh ;will be 0ffh if fstep has never moved drive hd jr nz,caldon ;if drive has already been calibrated ld hl,digit1 ;hl points to storage in memory for tens digit ld (hl),'?' ;store a '?' in tens digit inc hl ;hl points to storage in memory for ones digit ld (hl),'?' ;store a '?' in ones digit jr printxx ;return for next command caldon: call mkasci ;convert the hex track number to ascii chars printxx:call trkstr ;print the new drive's track number on the CRT jp comand ;return for next command drvstr: ld bc,2B28h ;B=column address w/offset,C=row addr w/offset call curadd ;move cursor to drive letter position ld a,(motdrv) ;get the binary drive number or 30h ;convert binary drive number to ASCII call outchra ;print the number on the screen ret ;**************************************************************** ;* * ;* SIDSEL ROUTINE * ;* * ;* TOGGLE THE CHOSEN SIDE, DISPLAY CHOICE ON CRT, * ;* STORE CHOICE FOR USE BY MOTRUN SUBROUTINE * ;* * ;**************************************************************** sidsel: ld a,(sidbit) ;current SIDE is coded into bit 2 xor 00000100b ;toggle bit 2 ld (sidbit),a ;save into memory call sidstr jp comand sidstr: ld bc,2B25h ;B=column address w/offset,c=row addr w/offset call curadd ;cursor address subroutine ld a,(sidbit) bit 2,a ;current side is coded into bit 2 ld a,'0' ;be ready to print a '0' jr z,chgsid ;if selected side is 0 inc a ;change '0' to '1' and be ready to print a '1' chgsid: call outchra ;print the character that is in register a ret ;**************************************************************** ;* * ;* SETSEC ROUTINE * ;* Get the sector number, display choice on the CRT. * ;* * ;**************************************************************** setsec: ld bc,2B26h ;B=column address w/offset,c=row addr w/offset call curadd ;cursor address subroutine call inchr ;get a character from the keyboard or buffer call valdig ;see if A register has ASCII 0 through 9 jr c,setsec ;valdig returns with carry set if not 0 thru 9 ; cp '0' ; jr c,setsec ;if typed character < '0' ; cp '9'+1 ; jr nc,setsec ;if typed character < or = '9' sub '0' ;make the sector number hexidecimal ld (sector),a ;store selected sector number in memory call secstr ;print the sector number on the CRT jp comand secstr: ld bc,2B26h ;B=column address w/offset,c=row addr w/offset call curadd ;cursor address subroutine ld a,(sector) ;get the sector number (in hex) from memory or '0' ;make the sector number an ASCII digit call outchra ;print the character that is in register a ret ;**************************************************************** ;* * ;* DENSITY ROUTINE * ;* * ;* TOGGLE THE DENSITY SELECTION, DISPLAY CHOICE ON CRT. * ;* * ;**************************************************************** density:ld a,(denbit) ;current density is coded into bit 6 ld e,01000000b xor e ;toggle bit 6 in register A ld (denbit),a ;save new byte into memory call denstr jp comand denstr: ld bc,2B23h ;B=column address w/offset,C=row addr w/offset call curadd ;cursor address subroutine ld a,(denbit) bit 6,A ;current density is coded into bit 6 ld de,denmfm ;point to string "MFM" to print jr nz,chgden ;if selected density was FM ld de,denfm ;was "MFM", point to string "FM" to print chgden: call outstr ;print the string that DE points to ret ;**************************************************************** ;* * ;* HEADER ROUTINE * ;* * ;* Get I.D. information from a sector header. * ;* * ;**************************************************************** header: call cmdnew ;is data port ready to receive a new command? ld a,(denbit) ;density bit is 6: 0=FM, 1=MFM or 00001010b ;merge the READ ID command with the density bit out (0FBh),a ;send READ ID command to NEC 765 data port call cmdrdy ;is data port ready to receive a command byte ld a,(sidbit) ;get side select bit ld e,a ;save side select bit in register E ld a,(motdrv) ;bit 0=US0, BIT 1=US1 for drive selection or e ;merge head select bit with drive select bits out (0FBh),a ;byte 2 of READ ID command call indata ;get the 7 result bytes of the READ ID command jp headout ;print the 7 result bytes on the CRT ;**************************************************************** ;* * ;* DATA ROUTINE * ;* * ;* Read undeleted data from selected drive, track, head, * ;* and sector. * ;* * ;**************************************************************** data: ld bc,3926h ;B=column address w/offset,C=row addr w/offset call curadd ;cursor address subroutine call cmdnew ;is data port ready to receive a new command ld a,0;(MT)<<<<<<<<;MT is multi-track flag (bit 7) ld e,a ;E contains multi-track flag (MT) ld a,0;(SK)<<<<<<<<;SK is skip deleted data address mark (bit 5) or e ;merge SK and MT bits ld e,a ;E contains SK and MT bits ld a,(denbit) ;density is coded into bit 6: 0=FM, 1=MFM or e ;merge SK and MT bits with density bit ld e,a ;E contains SK, MT, and density bits or 00000110b ;NEC 765 read data command code out (0FBh),a ;send read data command to NEC 765 data port ;*The following 6 lines are identical with those in the format command ;*and could therefore be a subroutine. call cmdrdy ;is data port ready to receive a command byte? ld a,(sidbit) ;bit 2: 0=side 1, 1=side 1 ld e,a ;save side select bit in register E ld a,(motdrv) ;bit 0=US0, BIT 1=US1 for drive selection or e ;merge head select bit with drive select bits out (0FBh),a ;byte 2 of read data command call cmdrdy ;is data port ready to receive a command byte? ld a,(curtrb) ;C: current track number out (0FBh),a ;send command byte to NEC 765 data port call cmdrdy ;is data port ready to receive a command byte? ld a,(sidbit) ;get side bit (in bit 2) rrca ;shift side bit into bit 0 rrca ;H: head number out (0FBh),a ;send command byte to NEC 765 data port call cmdrdy ;is data port ready to receive a command byte? ld a,(sector) ;R: sector number out (0FBh),a ;send command byte to NEC 765 data port ;*the following 3 lines are the same as used in the format command call cmdrdy ;is data port ready to receive a command byte? ld a,03 ;N: bytes per sector (03=1024 selected) out (0FBh),a ;send command byte to NEC 765 data port call cmdrdy ;is data port ready to receive a command byte? ld a,05 ;EOT: end of track (last sector to read) out (0FBh),a ;send command byte to NEC 765 data port call cmdrdy ;is data port ready to receive a command byte? ld a,30h ;GPL: gap length out (0FBh),a ;send command byte to NEC 765 data port call cmdrdy ;is data port ready to receive a command byte? ; im2 ld hl,4C00h ;HL points to sector buffer in RAM ; ld a,high stack ;high byte of interrupt table address ; ld i,a ;in IM3 interrupts will get a jump addr at XX7F ld a,0FFh ;DTL: data length use 0FFh if N not equal 0 out (0FBh),a ;send command byte to NEC 765 data port ; call mddly ;delay 12.5 uS waitdat: ;ei ; ld de,0FFFFh ;timeout count ;waitdec: ;dec e ;decrement low byte of count ;jr nz,waitdec ;if low byte not zero ;dec d ;decrement high byte of count ;jr z,get7 ;if timed out ;jr waitdec ;continue the loop ;halt ;wait for interrupt (meaning data byte ready) ;ldbyte: in a,(0FAh) ;read NEC 765 status port anä 11100000b ;savå data input/output,request for master bits cp 11000000b ;has execution phase ended/result phase started jr z,get7 ;if result phase has begun cp 11100000b ;is data port ready to send data? jp nz,waitdat ;loop until ready in a,(0FBh) ;read a byte of data ld (hl),a ;put the data byte into RAM inc hl ;point to next RAM location push ix ;delay by total of 25 clock cycles for these 2 pop ix ; instructions. JR WAITDAT ;go wait for the next byte ;pop de ;remove 2 bytes from stack pushed at interrupt ;ld a,h ;5000h-4C00h=400h=1024d ;cp 050h ;done if have reached 50h ;jr nz,waitdat ;if haven't read all bytes from the sector get7: ;di ;in case entered here on a timeout call indata ;read the 7 result bytes ST0,ST1,ST2,C,H,R,N call headout ;print the 7 result bytes on the CRT jp comand ;**************************************************************** ;* * ;* STEPI ROUTINE * ;* * ;* INCREMENT THE ASCII REPRESNTATION OF THE CURRENT TRACK * ;* NUMBER BY ONE (IF NOT ALREADY HIGHEST TRACK). PRINT IT * ;* ON THE CRT. * ;* * ;**************************************************************** ;*microdecision step in routine stepi: ld a,(maxtrb) ;A= highest allowed track number ld b,a ;B= highest allowed track number call pcn ;get pointer to present drive's PCN in HL ld a,(hl) ;A= present drive's present track number cp b ;is current track < highest allowed track jp nc,comand ;don't step in if now =or>highest allowed track inc a ;increment track number by 1 jr step ;**************************************************************** ;* * ;* STEPO ROUTINE * ;* * ;* DECREMENT THE ASCII REPRESNTATION OF THE CURRENT TRACK * ;* NUMBER BY ONE (IF NOT ALREADY LOWEST TRACK). PRINT IT * ;* ON THE CRT. * ;* * ;**************************************************************** stepo: call pcn ;get pointer to present drive's PCN in hl ld a,(hl) ;present drive's present track number cp 0 ;lowest allowed track number jp z,comand ;don't step out if already at track 0 dec a ;decrement track number by 1 step: ld (curtrb),a ;save the track number call mkasci ;convert track number to ascii characters call trkstr ;print the new track number on crt jp mdseek ;go do the seek ;**************************************************************** ;* * ;* SLEEP ROUTINE * ;* Delay for selected time. * ;* Enter up to four digits followed by "M" (for * ;* milliseconds. * ;* See the table in the data/storage section at the end * ;* of this program for an idea of how multipliers and the * ;* ones, tens, hundreds, and thousands digits are stored * ;* in memory. * ;**************************************************************** sleep: call outchra ;display the 'Z' (caused entry) on the screen ld a,0 ;initialize count of digits from keybord/buffer ld (digcnt),a ;initialize count of digits from keybord/buffer getzdig:push hl call inchr ;get a character from buffer or terminal pop hl cp 'm' ;follow the entered digits with (M)illiseconds jr z,zdelay ;if 'M'entered go perform the delay cp 'M' ;check for uppercase M jr z,zdelay ;go calculate and do the delay if uppercase M call valdig ;see if A register has ASCII 0 through 9 jr c,getzdig ;valdig returns with carry set if not 0 thru 9 call outchra ;display the character on the CRT and 0Fh ;change character from ASCII to a number ld e,a ;save the number for storage into memory ld hl,zdigit ;pointer to most recently received character ld c,4 ;count of decimal digits to shift in HL regstrs shift: ld a,(hl) ;get a character that was stored in memory ld (hl),e ;replace previously received char into memory ld e,a ;save the character that was stored in memory inc hl ;point to the next memory location inc hl inc hl dec c ;decrement count of decimal digits to shift jr nz,shift ;if all 4 digits haven't been shifted yet ld a,(digcnt) ;get count of digits from the keyboard/buffer inc a ;increment count of digits that were entered cp 4 ;maximum number of digits that may be entered ld (digcnt),a ;save count of digits from the keyboard/buffer jr nz,getzdig ;go get another character zdelay: ld c,4 ;count of digits to multiply by exx ld hl,0000 ;initialize the total exx ldnmbr: dec hl ;point to multiplier (1,10,100, or 1000) ld d,(hl) ;load low byte of multiplier into E dec hl ;point to high byte of multiplier ld e,(hl) ;load high byte of multiplier into D dec hl ;point to entered digit ld a,(hl) ;get entered decimal digit from memory ld (hl),0 ;replace entered digits w/0 for next sleep use dlayadd: and a ;test if decimal number is zero jr z,nxtnmbr ;if zero push de ;save multiplier (1,10,100, or 1000) exx ;save hl pointer; get total pop de ;get multiplier add hl,de ;add 1,10,100, or 1000 one time dec a ;subtract 1 from entered digit exx ;get pointer jr dlayadd nxtnmbr: dec c ;decrement count of decimal digits to add up jr nz,ldnmbr ;if entered digits are remaining exx dly1ms: ld de,085d ;(10)count for generating 1 millisecond delay ld a,l ;(4) or h ;(4)see if hl has decremented to 0 yet jr z,dlydone ;(10)if there are no milliseconds left to delay dlaylp: dec de ;takes(6)clock cycles (4000 cycles/millisecond) ld a,d ;(4) or e ;(4)see if de has decremented to 0 yet jr nz,dlaylp ;this instruction takes (7/12) clock cycles dec hl ;(6)decrement count of milliseconds remaining jp dly1ms ;(10) dlydone:ld a,(bufcnt) ;count of chars left to get from buffer, if any or a ;see if any characters left to get from buffer jr nz,dlyret ld a,(digcnt) ;count of digits entered in sleep routine inc a ;blank out the 'Z' also ld b,a ;number of times to send string ld de,bsspbs ;address of string backspace, space, backspace call multstr dlyret: jp comand ;**************************************************************** ;* * ;* SUBROUTINE MKASCI * ;* * ;* 1. ON ENTRY, A CONTAINS THE HEX TRACK NUMBER THAT WAS * ;* STORED BY NEC 765 RESULT COMMAND. * ;* 2. CONVERT IT TO TWO ASCII DIGITS AND STORE THEM FOR * ;* USE BY THE TRKCRT ROUTINE (WHICH PRINTS THEM TO THE * ;* CRT). * ;* 3. Enter at HEXASCI with A containing a hex number to * ;* convert to a pair of ASCII digits and HL containing * ;* a pointer to a sequential pair of addresses in which * ;* to store the resulting ASCII bytes. * ;* * ;**************************************************************** mkasci: ld hl,digit1 ;hl points to storage in memory for tens digit ld b,10 ;prepare to subtract 10s from the hex number call asc inc hl ;HL points to storage in memory for ones digit add a,b ;add the 10 that was subtracted to make neg. # ld b,1 ;prepare to subtract 1s from the hex number asc: ld (hl),'0' ;initialize the stored ASCII digit to '0' ascsub: sub b ;find the number of 10s or 1s in the hex number ret c ;if less then 10 or 1 remains in the hex number inc (hl) ;bump the stored ASCII digit higher jr ascsub ;**************************************************************** ;* * ;* TRACK ROUTINE * ;* * ;* This routine is entered when a digit (within allowable * ;* range of track number) is typed when the program is * ;* waiting for a command. This routine stores that digit, * ;* gets another digit (range check is performed), displays * ;* the digits on the screen, and sends the head to the * ;* selected track. * ;* * ;**************************************************************** track: ld (digit1),a ;save the first digit (in ASCII) ld bc,2B24h ;B=column address w/offset,C=row addr w/offset call curadd ;move cursor to track number position ld a,(digit1) call outchra ;print the first digit (from register a) get2nd: call inchr ;get the 2nd digit of track number ld (digit2),a ;save the second character call valdig ;see if A register has ASCII 0 through 9 jr c,get2nd ;valdig returns with carry set if not 0 thru 9 ; cp '0' ; jr c,get2nd ;if typed character < '0' ; cp '9'+1 ; jr nc,get2nd ;if typed character < or = '9' ld hl,digit1 ;HL points to memory storage of hi ASCII digit call calctr ;calculate current track in binary (HL points) ld a,(maxtrb) ;maximum allowed track number in binary sub (hl) ;HL points to current track in binary jr c,get2nd ;2nd digit was too large dec hl ;HL points to track number low digit in ASCII ld a,(hl) ;A=track number low digit in ASCII call outchra ;print the second digit (from register A) jp mdseek ;go do the seek ;************************************************************************ ;* * ;* MAXTRK ROUTINE * ;* * ;* Get two digits from the console. These two digits are the * ;* maximum track number beyond which the drive is not allowed * ;* to step. Save these digits in ASCII in MAXTRH and MAXTRL. * ;* * ;************************************************************************ maxtrk: ld bc,2B22h ;B=column address w/offset,C=row addr w/offset call curadd ;cursor address subroutine ld hl,maxtrh ;point to memory storage for max track hi digit ;*NOTE: registers HL must be preserved across these calls* call maxtr1 inc hl call maxtr1 dec hl ;point to DIGIT1 (needed by CALCTR) call calctr ;calculate and store maximum track in binary jp comand maxtr1: call inchr ;get 1st digit of the maximum track number ld (hl),a ;save the first ASCII digit (DIGIT1) call valdig ;see if A register has ASCII 0 through 9 jr c,maxtr1 ;valdig returns with carry set if not 0 thru 9 call outchra ;print the first digit (from register a) ret cylstr: ld bc,2B22h ;B=column address w/offset,C=row addr w/offset call curadd ;cursor address subroutine ld a,(maxtrh) call outchra ;print the first digit (from register a) ld a,(maxtrl) call outchra ;print the second digit (from register a) ret ;************************************************************************ ;* * ;* FORMAT ROUTINE * ;* Formats a microdecision drive track. * ;* * ;************************************************************************ format: ld bc,3136h ;B=column address w/offset,C=row addr w/offset call curadd ;cursor address subroutine ld a,0 ;initialize count value ld (chrns),a ;count of sector information requests call cmdnew ;is data port ready to receive a new command ld a,(denbit) ;density is coded into bit 6: 0=FM, 1=MFM or 00001101b ;NEC 765 format a track command code out (0FBh),a ;send format a track cmd to NEC 765 data port call cmdrdy ;is data port ready to receive a command byte ld a,(sidbit) ld e,a ;save side select bit in register E ld a,(motdrv) ;bit 0=US0, BIT 1=US1 for drive selection or e ;merge head select bit with drive select bits out (0FBh),a ;byte 2 of format a track command call cmdrdy ;is data port ready to receive a command byte? ld a,03 ;N: bytes per sector (03=1024 selected) out (0FBh),a ;send command byte to NEC 765 data port call cmdrdy ;is data port ready to receive a command byte? ld a,05 ;SC: sectors per track out (0FBh),a ;send command byte to NEC 765 data port call cmdrdy ;is data port ready to receive a command byte ld a,05Fh ;GPL: gap three out (0FBh),a ;send command byte to NEC 765 data port im0 call cmdrdy ;is data port ready to receive a command byte? ld a,0BAh ;D: filler byte ld hl,hdrinfo ;point to start of header information buffer out (0FBh),a ;send command byte to NEC 765 data port ;************************************************************************ ;* SUBROUTINE CHRN * ;* Gets the cylinder number, head, sector number, and bytes per * ;* sector that is needed as part of some of the NEC 765 commands, * ;* including the format a track command. * ;************************************************************************ chrn: ei halt ;wait for an interrupt ld a,(hl) ;get a byte from header information table out (0FBh),A ;send byte to NEC 765 data port inc hl ;increment pointer to header information table ld a,(chrns) ;old count number inc a ;add 1 to make new sector number ld (chrns),a ;save incremented count number cp 20 ;5*4=20(# of sectors)*(bytes called for/sector) jr nz,chrn ;if have not supplied C,H,R,N for all sectors call indata ;read ST0, 1, 2, C, H, R, N jp comand hdrinfo:db 87h,01h,04h,03h ;CHRN for first sector db 76h,00h,03h,03h ;CHRN for second sector db 65h,01h,02h,03h ;CHRN for third sector db 54h,00h,01h,03h ;CHRN for forth sector db 43h,01h,00h,03h ;CHRN for fifth sector ;************************************************************************ ;* * ;* SUBROUTINE INDATA * ;* * ;************************************************************************ indata: ld hl,datbuf ;7 memory bytes for temporary result storage ld b,7 ;there are 7 result bytes to be read indat9 calì rdrdù ;is NEC 765 ready to send another result byte in a,(0FBh) ;read a result byte ld (hl),a ;temporarily store this result byte inc hl ;point to next temporary storage location dec b ;one less result byte remains to be read jr nz,indat9 ;if more result bytes remain to be read ret ;************************************************************************ ;* * ;* SUBROUTINE HEADOUT * ;* Prints ST0, ST1, ST2, and CHRN (obtained from READ ID * ;* command and read data command) on the CRT. * ;* * ;************************************************************************ headout:ld bc,5B20h ;B=column address w/offset,C=row addr w/offset ld a,(datbuf+5) ;datbuf+3=record (sector) number byte of result add c ;add row number to cylinder number ld c,a ;prepare bc register pair for call to curadd call curadd ;move cursor to data display position ld hl,datbuf-1 ;7 result bytes are stored in datbuf ld b,7 ;7= count (number of bytes in result) indat: inc hl push bc push hl ld a,(hl) ;get a result byte frm temporary memory storage ld ix,indat1 jp lbyte ;convert the a register to ascii and print indat1: ld a,' ' ;ascii space call outchra ;print a space pop hl pop bc ;get count dec b ;decrement count jr nz,indat ;if all 7 bytes not yet printed jp comand ;done if all 7 bytes have been printed ;**************************************************************** ;* * ;* CURADD SUBROUTINE * ;* * ;* DIRECT CURSOR ADDRESSING SUBROUTINE: upon entry * ;* to CURADD reg. B should contain COLUMN address with * ;* offset. Reg. C should contain ROW address with offset. * ;* * ;**************************************************************** curadd: ld a,b ld (col),a ;store column (addr+offset) ld a,c ld (row),a ;store row (address+offset) ld a,1Bh ;esc character-TERMINAL DEPENDENT call outchra ;print the character in register A ld a,'=' ;= character-TERMINAL DEPENDENT call outchra ;output character in register a ld a,(curflg) bit 3,a ;cursor addressing order bit jp nz,colout rowout: ld a,(col) ;output column address call outchra ;print the character that is in reg A ret nz ;is column next or are we done ? colout: ld a,(row) ;output row address call outchra ;print the character that is in reg A jr nz,rowout ;is row next or are we done ? ret ;************************************************************************ ;* * ;* SUBROUTINE VALDIG * ;* * ;* Enter with a character in A. This subroutine checks the * ;* character and returns with the carry cleared if the character * ;* is between ASCII 0 and 9 (30h through 39h). If A contained * ;* anything else this subroutine returns with the carry set. * ;* All registers are returned unchanged. * ;************************************************************************ valdig: cp '0' ;is the character is a digit (ASCII 0-9)? ret c ;return with carry set if char less than '0' cp '9'+1 ;this will clear carry if character '9' or less ccf ret ;return with carry set if char greater than '9' ;************************************************************************ ;* * ;* SUBROUTINE CALCTR * ;* * ;* Enter with hl pointing to memory location of a high order * ;* ASCII digit of a 2 digit decimal number. The next memory * ;* location is the low order ASCII digit. This routine * ;* calculates a binary byte out of the two ASCII digits. This * ;* byte is stored in the memory location following the low order * ;* ASCII digit. Also returns: * ;* A=binary byte * ;* HL=points to memory storage of binary byte * ;* * ;************************************************************************ calctr: ld a,(hl) ;maximum high decimal track digits in ASCII sub '0' ;maximum high decimal track digit in binary add a,a ;A=2*high decimal track digit ld b,a ;B=2*high decimal track digit add a,a ;A=4*high decimal track digit add a,a ;A=8*high decimal track digit add a,b ;A=10*high decimal track digit inc hl ;HL points to low order ASCII digit add a,(hl) ;A now=number+30h in binary sub '0' ;A now=number in binary inc hl ;point to memory storage for binary number ld (hl),a ;store binary number ret ;**************************************************************** ;* * ;* INCHR SUBROUTINE * ;* * ;* Checks the buffer to see if it has characters in it. * ;* Fetches a character from the buffer if there are any. * ;* Else fetches a character from the console. * ;* returns it in register A. and since this routine is * ;* nearly always running, it keeps the motor running by * ;* calling MOTRUN. * ;* * ;**************************************************************** ;*use microdecision sense drive status command to get status byte 3 (st3) and ;*to select the side inchr: call cmdnew ;is data port ready to receive a new command? ld a,04 ;sense drive status command out (0FBh),a ;issue the command call cmdrdy ;is data port ready to receive a command byte ld a,(sidbit) ;get head select bit (coded into bit 2) ld e,a ld a,(motdrv) ;bit 0=US0, BIT 1=US1 for drive selection or e ;merge head select bits with drive select bits out (0FBh),a ;byte 2 of drive status command ;*NOTE: reading the result is delayed until later in the INCHR routin in order ;*to keep side one selected (if it is) as long as possible ;** GET A CHARACTER FROM THE CONSOLE or from the batch command buffer ** ld a,(bufcnt) or a ;see if buffer count is 0, meaning buffer empty jr z,charin ;if buffer is empty dec a ;decrement count ld (bufcnt),a ;RESET count OF CHARS LEFT TO GET FROM BUFFER JR Z,BUFRES ;IF NO CHARACTERS LEFT TO GET FROM BUFFER call motrun in a,(status) ;read status register and rdbit jr z,frombuf ;no character entered,get character from buffer ;* BUFRES executes if character entered at keyboard to terminate buffer command bufres: xor a ;zero register A;prepare to exit batch command ld (bufcnt),a ;reset count of chars left to get from buffer ld (bufchr),a ;reset count of characters gotten from buffer ld bc,2729h ;B=column address w/offset,C=row addr w/offset call curadd ;move cursor to 'Command:' ld e,':' ;replace 'Command;' with 'Command:' call outchre ld a,(buftot) ;total number of chars originally in buffer ld b,a ;count of number of times... ld e,' ' ; ...to send blank space call chrfeed ld a,' ' ;dummy character to return to caller jp getst3 ;exit batch command, now get character from kbd frombuf:ld hl,(bufptr) ;get buffer pointer ld a,(hl) ;get a character from the buffer inc hl ;point to next character in the buffer ld (bufptr),hl ;save buffer pointer into memory ld hl,bufchr ;increment count of characters gotten from inc (hl) ; buffer so far ; scf ;return with carry set if character from buffer jr getst3 charin: call motrun in a,(status) ;read status register and rdbit jr z,charin ;no character ready, loop in a,(rdreg) ;read character and 07Fh ;strip parity ; scf ; ccf ;return with carry clear if char. from console getst3: push af ;preserve the character and the flag call rdrdy ;is data port ready to send a result byte? in a,(0FBh) ;read status byte 3 ld (st3),a ;save status register 3 information pop af ;retrieve the character and the flag ret ;**************************************************************** ;* * ;* SUBROUTINE MOTRUN * ;* * ;* KEEP MOTOR RUNNING IF MOTOR ON (MOTOGL=0FFh) SELECTED * ;* * ;* THIS ROUTINE RUNS ONCE BEFORE EACH CHECK FOR A * ;* CHARACTER FROM THE TERMINAL or the buffer. THIS MAKES * ;* THE MOTOR RUN. * ;* * ;**************************************************************** ;run the microdecision controlled motor motrun: ld c,00000001b ;motor on bit: prepared if motdrv is 0(drive 0) ld a,(motdrv) ;get the drive number (0-3) ld b,00010000b ;upper four bits will drive drive select lines jr drvtst ;see if the drive is drive 0 or not mddrv1: ld c,00000010b ;must be drive 1, 2,OR 3 (MD wants only 1 or 2) dec a ;try the next drive rlc b ;select next drive higher drive bit drvtst: or a ;see if correct drive has been reached jr nz,mddrv1 ;if haven't reached correct drive ld a,(motogl) ;see if motor has been selected to be on or a ; 0=off 1=on jp z,drivon ;if motor is not supposed to be on ld a,c ;A<--motor line;bit1=drive 0 motor;2=drive1,2,3 drivon: or b ;add in the drive select line to the motor line out (0F7h),a ;turn on selected microdecision drive (RV2 BDS) out (0F8h),a ;for rev. 1 microdecision boards ret ;**************************************************************** ;* * ;* SUBROUTINE TRKSTR * ;* * ;* 1. MOVE CURSOR TO TRACK NUMBER DISPLAY ON CRT * ;* 2. PRINT THE TWO ASCII TRACK DIGITS ON CRT * ;* * ;**************************************************************** trkstr: ld bc,2B24h ;B=column address w/offset,C=row addr w/offset call curadd ;move cursor to track number position ld a,(digit1) ;load the first digit call outchra ;print the character that is in register A ld a,(digit2) ;load the second digit call outchra ;print the character that is in register A ret ;************************************************************************ ;* * ;* SUBROUTINE MDSEEK * ;* * ;* STEPS THE MICRODECISION CONTROLLED DRIVE HEAD TO THE TRACK * ;* SPECIFIED IN BYTE MDTRK. THE SEEK COMMAND IS A THREE BYTE * ;* COMMAND. * ;* * ;************************************************************************ mdseek: call cmdnew ;is data port ready to receive a new command? ld a,0Fh ;NEC 765 seek command code out (0FBh),a ;send seek command to NEC 765 data port call cmdrdy ;is data port ready to receive a command byte ld a,(sidbit) ;bit 2 is 0 for side 0, 1 for side 1 ld e,a ld a,(motdrv) ;bit 0=US0, BIT 1=US1 for drive selection or e ;merge head select bits with drive select bits out (0FBh),a ;byte 2 of seek command call cmdrdy ;is data port ready to receive a command byte ld a,(curtrb) ;byte 3 selects the cylinder number (0-39) out (0FBh),a im0 ei halt ;wait for an interrupt call sensint ;sense interrupt status (to terminate command) jp comand ;************************************************************************ ;* * ;* SUBROUTINE SENSINT * ;* THIS ROUTINE PERFORMS THE SENSE INTERRUPT STATUS COMMAND OF * ;* THE NEC 765 DISK CONTROLLER. IT IS NECESSARY TO PERFORM THIS * ;* COMMAND FOLLOWING SEEK AND RECALIBRATE COMMANDS IN ORDER TO * ;* PROPERLY TERMINATE THEM. * ;* * ;************************************************************************ sensint:call cmdnew ;is data port ready to receive a new command? ld a,08 ;sense interrupt status command(clears FDD0-3) out (0FBh),a ;issue the command ld bc,4723h ;B=column address w/offset,C=row addr w/offset call curadd ;move cursor to ST0 position call rdrdy ;is data port ready to send a result byte? in a,(0FBh) ;read status 0 ld (ST0),a ;save status register 0 information ld ix,sen0 jp lbyte ;convert the a register to ascii and print sen0: call rdrdy ;is data port ready to send a result byte? call pcn ;returns pointer in HL to present drives PCN in a,(0FBh) ;read present cylinder number ld (hl),a ;store pcn in appropriate byte for present driv LD A,(ST0) ;get status register 0 information read earlier and 11100000b ;save interrupt code (7,6)and seek end bits (5) cp 10000000b ;bit 7=1, 6=0 --> invalid command-never started jr z,sensint ;if invalid command or not done, start over ret ;************************************************************************ ;* * ;* SUBROUTINE PCN * ;* * ;* FOR THE MICRODECISION, RETURNS A POINTER IN HL TO THE PRESENT * ;* DRIVES PRESENT CYLINDER NUMBER. THE TABLE IS FILLED BY STORING * ;* THE RESULTS OF THE NEC 765 SENSE INTERRUPT STATUS COMMAND * ;* (RESULT SUBROUTINE). * ;* * ;************************************************************************ pcn: ld hl,pcntbl-1 ;table of each of 4 drives present cylinder #s ld a,(motdrv) ;present drives number inc a nextdr: inc hl ;develop a pointer (in HL) to byte for present dec a ; cylinder number for present drive jp nz,nextdr ret ;************************************************************************ ;* * ;* SUBROUTINE CMDNEW * ;* * ;* READS MICRODECISION PORT 0FAh TO GET THE STATUS OF THE NEC 765 * ;* CONTROLLER CHIP. THIS IS A CHECK TO SEE IF THE CHIP IS READY * ;* FOR THE NEXT BYTE OF A COMMAND WHICH IS ALREADY IN PROGRESS. * ;* * ;************************************************************************ CMDNEW: CALL MDDLY ;DELAY 12.5 uS IN A,(0FAh) ;READ NEC 765 STATUS PORT AND 11110000b ;MASK OUT SOME BITS CP 10000000b ;IS DATA PORT READY FOR A NEW COMMAND? JP NZ,CMDNEW ;LOOP UNTIL READY RET ;************************************************************************ ;* * ;* SUBROUTINE CMDRDY * ;* * ;* READS MICRODECISION PORT 0FAh TO GET THE STATUS OF THE NEC 765 * ;* CONTROLLER CHIP. THIS IS A CHECK TO SEE IF THE CHIP IS READY * ;* FOR THE NEXT BYTE OF A COMMAND WHICH IS ALREADY IN PROGRESS. * ;* * ;************************************************************************ cmdrdy: call mddly ;delay 12.5 uS in a,(0FAh) ;read NEC 765 status port and 11010000b ;mask out some bits cp 10010000b ;is data port ready for more bytes of command? jp nz,cmdrdy ;loop until ready ret ;************************************************************************ ;* * ;* SUBROUTINE RDRDY * ;* * ;* READS MICRODECISION PORT 0FAh TO GET THE STATUS OF THE NEC 765 * ;* CONTROLLER CHIP. THIS IS A CHECK TO SEE IF THE CHIP IS READY * ;* FOR THE NEXT BYTE OF THE RESULT. * ;* * ;************************************************************************ rdrdy: call mddly ;delay 12.5 uS in a,(0FAh) ;read NEC 765 status port anä 11100000b ;savå data input/output,request for master bits cp 11000000b ;is data port ready to send data? jp nz,rdrdy ;loop until ready ret ;************************************************************************ ;* * ;* SUBROUTINE MDDLY * ;* * ;* DELAYS 12 uS. 12uS IS THE MINIMUM TIME REQUIRED BETWEEN BYTES * ;* BEING OUTPUT TO THE NEC 765. * ;* 12.5uS = (50 CYCLES)/(4 MHZ) * ;* * ;************************************************************************ mddly: ex (sp),ix ;23 clock cycles to execute this instruction ex (sp),ix ;23 more clock cycles ret ; 1 clock cycle for ret (3 cycles for call) ;************************************************************************ ;* * ;* SUBROUTINE MULTSTR * ;* * ;* Send string of characters pointed to by registers DE to the * ;* CRT the number of times contained in B. * ;* * ;************************************************************************ multstr:PUSH DE ;SAVE A COPY OF THE STRING ADDRESS CALL OUTSTR POP DE DEC B ;DECREMENT NUMBER OF TIMES TO SEND STRING jr nz,multstr RET ;************************************************************************ ;* * ;* SUBROUTINE OUTSTR * ;* * ;* Enter with DE pointing to a string to send to the CRT. The * ;* string must be terminated with a '$' character. * ;* * ;************************************************************************ outstr: ld a,(de) ;get a character of the string to be printed cp '$' ;end of string marker ret z push de call outchra ;if character was not '$' then print it pop de inc de ;point to the next character in the string jr outstr ;go do the next character ;**************************************************************** ;* * ;* SUBROUTINE LNFEEDS and CHRFEED * ;* * ;* To send linefeeds enter at lnfeeds with register B * ;* containing number of times to send a line feed * ;* character (0Ah) to the screen. Enter at chrfeed with * ;* register E containing character to send and register B * ;* containing number of times to send it. * ;* * ;**************************************************************** lnfeeds:ld e,lf ;character to send (ASCII line feed) chrfeed:call outchre ;send line feed to screen dec b ;count <-- count-1 jr nz,chrfeed ;if haven't sent char required number of times ret ;**************************************************************** ;* * ;* OUTPUT A CHARACTER TO THE CRT * ;* * ;* enter at OUTCHRA if character to send is in register A * ;* enter at OUTCHRE if character to send is in register E * ;* * ;* All registers are preserved except the alternate AF * ;* registers if entered at outchre. The e register is * ;* also lost if entered at outchra. * ;* * ;**************************************************************** outchra:ld e,a ;routine entered with character to print in A outchre:ex af,af' ;exchange to preserve flags outchr: in a,(status) ;Get communications port status and wrbit ;test if ready to send a character jr z,outchr ;loop if not ready ld a,e ;get the character to print from register E out (wrreg),a ;Output to transmitter buffer ex af,af' ;get back flags routine was entered with ret screen: db cr db 'uDecision Investigation Tool rev. 2.5' db CR,LF db 'Copyright 1989 Ronald E. Jacobs (Berkeley, CA)' db lf,cr db 'max ^Trk step In/Out ST0' db CR,LF db 'F density read Headers ST1' db CR,LF db 'NN track cursor Addressing ST2' db CR,LF db 'Side Recalibrate ST3' db CR,LF db 'seCtor read Data' db cr,lf db 'Motor ^Format a track' db CR,LF db 'L drive ^C exit' db cr,lf db 'Command:' db '$' DENFM: db 'FM $' DENMFM: db 'MFM$' OFFMSG: db 'OFF$' ONMSG: db 'ON $' BSCOLON:db bs,';$' ;used by filbuf to put a ';' after Command: BSSPBS: db bs,' ',bs,'$';used to blank the character before the cursor ;************************************************************************ ;* * ;* The following bytes are moved into ram when fstep is entered. * ;* They are here because fstep is operating from ROM but needs * ;* these bytes in RAM so that they can be changed dynamically. * ;* * ;************************************************************************ MV2RAM: .phase stack ;must be at 427Fh as format interupts go here denbit: db 01000000b ;0100$0000 =MFM 0000$0000 =FM sidbit: db 00000000b ;0000$0100 =drive side 1 0000$0000 = side 0 curflg: db diradfg ;0000$1000 cursor direct address sequence order flag motogl: db 0 ;motor toggle flag ;*The order of the next 3 bytes must not be changed (for subroutine CALCTR)* digit1: db '?' ;makes ASCII track number (tens digit) digit2: db '?' ;initially not known (='??') (ones digit) curtrb: db 99 ;current track number in binary motdrv: db 0 ;drive #(filled by routine seldrv) ;*The order of the next 3 bytes must not be changed (for subroutine CALCTR)* maxtrh: db '3' ;maximum high decimal track digit in ASCII maxtrl: db '9' ;maximum low decimal track digit in ASCII maxtrb: db 39 ;maximum track number in binary PCNTBL: ;0FFh=FSTEP has never accessed this drive PCN0: db 0FFh ;DRIVE 0 PRESENT CYLINDER NUMBER PCN1: db 0FFh ;DRIVE 1 PRESENT CYLINDER NUMBER PCN2: db 0FFh ;DRIVE 2 PRESENT CYLINDER NUMBER PCN3: db 0FFh ;DRIVE 3 PRESENT CYLINDER NUMBER sector: db 05 ;sector number to READ DATA from chrns: db 1 ;used by FORMAT:count of CHRNs requested bufcnt: db 0 ;count of chars remaining in batch cmd buffer bufchr: db 0 ;number of characters gotten so far from buffer bufptr: dw cmdbuf ;pointer to char. in command buffer(0FEh long) buftot: dw 0 ;total number of characters entered in buffer ;** The order of the following 8 lines of ds and dw must not change for SLEEP** zdigit: db 0 ;most recently recieved digit in sleep command dw 0001d ; 1s multiplier db 0 ;digit storage(10s when all digits entered) dw 0010d ; 10s multiplier db 0 ;digit storage (100s) dw 0100d ; 100s multiplier db 0 ;digit storage (1000s)(least recently received) dw 1000d ;1000s multiplier DIGCNT: DB 0 ;COUNT OF ENTERED DIGITS IN SLEEP COMMAND st3 equ $ ;1 byte uninitialized storage status reg. 3 row equ st3+1 ;1 byte uninitialized storage col equ row+1 ;1 byte uninitialized storage datbuf equ col+1 ;7 bytes uninitialized storage(ST0,1,2,C,H,R,N) st0 equ datbuf ;status register 0 st1 equ st0+1 ;status register 1 st2 equ st1+1 ;status register 2 cmdbuf equ datbuf+7 ;255 bytes uninitialized storage for batch cmd .dephase ENDMV2: ;END OF ASSEMBLED CODE ENDIF ;END OF "IF ALIGNMENT" CONDITIONAL ;************************************************************************ ;* * ;* INITIALIZATION STRINGS FOR MD2 AND MD3 UARTS AND TIMER * ;* * ;* Everything after this point may be overwritten after * ;* the program begins operating. * ;* * ;************************************************************************ IF MD3 init_tab: db 0f3h ;CTC channel 0, mode 3 db 3eh db 0f0h ;CTC channel 0 set to max delay db 0ffh db 0f0h db 0ffh db 0f3h ;CTC channel 1, mode 3 db 7eh db 0f1h ;CTC channel 1 set to 9600 baud db 0dh db 0f1h db 0 db 0f3h ;CTC channel 2, mode 3 db 0beh db 0f2h ;CTC channel 2 set to 1200 baud db 68h db 0f2h db 0 db s1stat ;reset both UARTS db 80h db s2stat db 80h db s1stat db 80h db s2stat db 80h db s1stat db 40h db s2stat db 40h ;end of reset sequence db s1stat ;set both UARTS db 0ceh ;8 bits, no parity, x16, 2 stop db s2stat db 0ceh db s1stat ;Tx, Rx - on, DTR, RTS - on, ER reset db 37h db s2stat db 37h init_len equ ($-init_tab)/2 ENDIF ;ENDIF OF IF MD3 ;************************************************************************ ;* * ;* The following macro calls cause the variable following the % * ;* sign to be printed on the CRT when this program is assembled. * ;* * ;************************************************************************ endall equ $-1 ;ending address of all code and data codelen equ $-serinit ;total code length .radix 16 ;change radix to base 16 for following macros if2 ;if2 assembles only on 2nd pass of 2 pass mode else ;give the following information only on first pass oncrt 'Start of all code SERINIT',%serinit if monitor oncrt 'Monitor program re-entry address STRT ',%strt endif if alignment oncrt 'Alignment program start address ALIGN ',%align endif oncrt 'Ending address of all code and data ENDALL ',%endall oncrt 'Total code length is ',%codelen endif .radix 10 ;return to default radix end