; Program to transmit a CP/M file through a serial port ; Accesses port directly, bypassing the BDOS ; Assumes an 8-bit word length and no parity ; ; Version of 9/2/83 ; ; Code Z80 optimized ; Adapted for JOYCE machine, version of 12/3/88 ; ; BOOT equ 0000h ; CP/M reboot address BDOS equ 0005h ; CP/M BDOS entry point TFCB equ 005ch ; FCB for file to be transmitted .drv equ 1 _CR equ 32 .conin equ 1 .string equ 9 .keysta equ 11 .open equ 15 .rdseq equ 20 .setdma equ 26 bell equ 07h lf equ 0ah cr equ 0dh eol equ '$' NULL equ 00h NXREC equ 01h NEWREC equ 02h EOF equ 03h EOT equ 04h RETRC equ 4 NOMSB equ 7fh SIOsta equ 0e1h ; SIO status port SIOdat equ 0e0h ; SIO data port iflag equ 00000001b ; Input flag for serial port oflag equ 00000100b ; Output flag for serial port siores equ 00010000b ; Reset bit bufrec equ 128 ; Buffer size (CP/M records) ; _USERF equ 30 ; SA_INIT equ 00b6h SA_PARA equ 00bch ; ; aseg org 0100h ; jp SIOini ; Go to start ; ; Serial port initialization code here ; ; Call XBIOS ; USERF: push hl push de ld hl,(BOOT+1) ; Fetch base of BIOS ld de,3*(_USERF-1) add hl,de ; Build XBIOS vector pop de ex (sp),hl ; Fetch address ret ; Execute it ; ; Set an 8-bit word length and no parity ; SIOini: call USERF dw SA_PARA ; Get current parameters ld l,8 ; Bit length ld h,l ld a,0 ; No handshake ld d,1 ; One stop bit ld e,0 ; No parity call USERF dw SA_INIT ; Set parameters ; tx: ld a,(TFCB+.drv) cp ' ' ; Check for filename jr nz,open ld de,fnmer ; Print error message and reboot abort: call string ld e,EOT call xmtbyt ; Send EOT character jp BOOT ; Return to CP/M open: ld de,TFCB ld c,.open call BDOS ; Open file inc a jr nz,found ; File present ld de,fnfer ; Point at error message jr abort ; Print and reboot found: xor a ld (TFCB+_CR),a ; Set next record byte to zero ld c,a ; Set record count in buffer to zero ready: push bc ; Save rerord count ld c,.keysta call BDOS ; Get console status or a jr z,ready ; No key pressed push bc ld c,.conin call BDOS pop bc cp 'C'-'@' jr nz,ready1 endxmt: ld de,eotmsg ; Print EOT message and abort jr abort ready1: call recbyt ; Read serial port jr z,ready ; Wait for character to be received cp EOT jr z,endxmt ; End transmission cp NXREC jr z,xmtrec ; Transmit next record cp NEWREC jr nz,ready ; Ignore other characters ld hl,(datptr) ld de,-bufrec add hl,de ; Point at last record ld (datptr),hl inc c ; Go back one record xmtrec: dec a ld (rptflg),a ; Save repeat flag call z,count ; Increase record message if new record xmtrc1: dec c ; Decrease record count jp p,xmtrc2 ; More in buffer ld a,(eofflg) or a jr z,readfl ; More in file ld de,eofmsg call string ; Print EOF message ld e,EOF call xmtbyt ; Send EOF byte jp BOOT readfl: ld de,datbuf ld (datptr),de ; Point at beginning of data buffer inc c ; Initialize record count to zero read: push bc push de ld c,.setdma call BDOS ; Set DMA address ld de,TFCB ld c,.rdseq call BDOS ; Read next record pop de pop bc or a jr nz,nomore ; EOF detected ld hl,bufrec add hl,de ; Point at next record in buffer ex de,hl inc c ; Increase record count ld a,bufrec cp c jr nz,read ; Stop at end of extent jr xmtrc1 nomore: ld a,1 ld (eofflg),a ; Set EOF flag jr xmtrc1 xmtrc2: ld a,(rptflg) inc a ld e,a call xmtbyt ; Send response to request for record ld hl,(datptr) ; Point at next record to transmit ld b,bufrec ; Character count for record ld d,0 ; Checksun for record xmtrc3: ld a,(hl) ; Get next byte to send inc hl ; Update pointer ld e,a ; Save in E add a,d ld d,a ; Update checksum djnz xmtrc3 ; More in record ld e,d call xmtbyt ; Send checksum push bc ld b,RETRC ld e,NULL xmtrc4: call xmtbyt ; Send 4 NULs to replace any missed bytes djnz xmtrc4 ld (datptr),hl ; Save pointer to next record ld de,recmsg call string ; Print record message ld a,(rptflg) or a jr z,nextln ; Skip 'again' if successful first time ld de,again call string ; Print 'again' if record repeated nextln: ld de,crlf call string ; Print CRLF pop bc jp ready ; Go wait for next prompt to send ; ; Count records ; count: ld hl,recnum count1: inc (hl) ld a,'9' cp (hl) ; Over 9? ret nc ld (hl),'0' dec hl ld a,(hl) cp ' ' jr nz,count1 ld (hl),'0' jr count1 ; Put 0 in message ; ; Send data in reg E to SIO ; xmtbyt: call outrdy ; Wait for ready jr z,xmtbyt ld a,e out (SIOdat),a ret ; ; Check COMM ready for data ; outrdy: call cliost ; Reset SIO in a,(SIOsta) ; Get state and oflag ; Test bit ret ; ; Read serial data ; recbyt: call cliost in a,(SIOsta) ; Read serial status port and iflag ret z ; Wait for character to be received in a,(SIOdat) ; Get received character and NOMSB ; Mask off bit 7 for ASCII codes ret ; ; Clear the COMM status register ; cliost: ld a,siores out (SIOsta),a ; Simple reset ret ; ; Print standard string thru BDOS ; string: ld c,.string call BDOS ret ; fnmer: db 'File name missing',cr,lf,eol fnfer: db 'File not found',cr,lf,eol eofmsg: db 'Transfer complete',cr,lf,bell,eol eotmsg: db 'Transfer terminated',cr,lf,bell,eol recmsg: db 'Record #' reccnt: db ' ' recnum: db '0' ; Record # transmitted db ' transmitted',eol again: db ' again',eol ; Repeated record crlf: db cr,lf,eol ; CRLF sequence datptr: dw datbuf ; Pointcr to next data byte to send eofflg: db 0 ; Flag for EOF read rptflg: db 0 ; Flag for repeated record datbuf equ $ ; Data buffer ; end