TITLE 'UREAD - Read file from uSD card' ; ; code to read a file on the Micro Drive on ; prototype serial port B 1/2010 ; CR EQU 0dh ; carriage return LF EQU 0ah ; line feed BS EQU 8 ; backspace ADAT EQU 0 ; serial data port A BDAT EQU ADAT+1 ; serial data port B ACON EQU ADAT+2 ; console status port A BCON EQU ADAT+3 ; port B status reg. CPM EQU 0 ; return to cp/m BDOS EQU 5 ; BDOS entry CLSF EQU 16 DELF EQU 19 WRTF EQU 21 MAKF EQU 22 SDMA EQU 26 SFCB EQU 5ch ;system FCB ACK EQU 6 ; udrv ACK NACK EQU 15h ; udrv NACK ; ORG 100h URD: LD SP,STACK LD C,'U' CALL UDOUT CALL UDIN ; set up DMA addr. LD DE,BUFF LD C,SDMA CALL BDOS ; set up file fcb LD HL,SFCB LD DE,FCB LD BC,16 LDIR ; copy filename to udrv staging area ; remove spaces and add '.' LD HL,SFCB+1 LD DE,FNMG1 LD B,8 CFUD: LD A,(HL) CP ' ' JR Z,CFUD1 LD (DE),A INC DE INC HL DJNZ CFUD CFUD1: LD A,'.' LD (DE),A INC DE ; LD B,3 LD HL,SFCB+9 CFUD2: LD A,(HL) CP ' ' JR Z,CFUD3 LD (DE),A INC DE INC HL DJNZ CFUD2 CFUD3: LD A,0 LD (DE),A ; print out filename and size (later) LD DE,RDMSG CALL PSTNG LD DE,FNMG1 CALL PSTNG LD DE,SPACE CALL PSTNG ; init file LD DE,FCB LD C,DELF CALL BDOS LD DE,FCB LD C,MAKF CALL BDOS INC A JR NZ,GFIL LD DE,NODIRSPC CALL PSTNG JP CPM ; send read command to uDrv GFIL: CALL SFN LD C,0 CALL UDOUT ; receive 4 byte file size back LD B,4 LD HL,MSB GFL1: CALL UDIN LD (HL),C INC HL DJNZ GFL1 ; convert file size to what we can use LD A,(LSB) AND 1FH LD (LAST),A ; now determine # blocks to read (divide by 32) LD IX,MSB LD B,5 DETNB: OR A RR (IX+0) RR (IX+1) RR (IX+2) RR (IX+3) DJNZ DETNB ; display file size info. LD HL,MSB LD B,4 PSZ: LD A,(HL) CALL PHEX INC HL DJNZ PSZ LD DE,RECMSG CALL PSTNG LD A,(LAST) CALL PHEX LD DE,NDMSG CALL PSTNG ; number of blocks to read in msb ... lsb ; number of bytes in last block is in last ; now put bytes in proper order LD A,(MSB) LD B,A LD A,(MSB+1) LD (MSB),A LD A,B LD (MSB+1),A ; LD A,(MID) LD B,A LD A,(MID+1) LD (MID),A LD A,B LD (MID+1),A ; EXX LD DE,(MSB) ;# 32b blocks in alt. regs. LD HL,(MID) EXX ; set up to recv. them LD HL,BUFF GFL2: LD C,ACK CALL UDOUT LD B,32 GFL3: IN A,(BCON) AND 1 JR Z,GFL3 ;no udrv output IN A,(BDAT) LD (HL),A INC HL CALL CONIN DJNZ GFL3 CALL SHWACT ;show activity ; check if we read all full blocks EXX DEC HL LD A,H OR L JR NZ,GFL4 LD A,E OR D JP Z,GETLST DEC DE LD HL,(MID) GFL4: EXX ; see if buffer is full LD BC,BUFF+128 LD A,H CP B JR NZ,GFL2 LD A,L CP C JR NZ,GFL2 LD HL,BUFF PUSH HL PUSH BC LD DE,FCB LD C,WRTF CALL BDOS POP BC POP HL OR A JR Z,GFL2 LD DE,NOSPC CALL PSTNG JP CPM ; MSB: DB 0 ;msb of file size DB 0 MID: DB 0 LSB: DB 0 LAST: DB 0 ; activity indicator SHWACT: LD B,0 LD A,(OFFST) LD C,A PUSH HL LD HL,SYMBS ADD HL,BC LD C,BS CALL CONOUT LD C,(HL) CALL CONOUT POP HL LD A,(OFFST) INC A CP 4 JR NZ,SAVO LD A,0 SAVO: LD (OFFST),A RET ; OFFST: DB 0 SYMBS: DB '\|/-' ; figure out how to send last part of file GETLST: EXX LD BC,BUFF+128 LD A,H CP B JR NZ,PART LD A,L CP C JR NZ,PART LD HL,BUFF PUSH HL PUSH BC LD DE,FCB LD C,WRTF CALL BDOS POP BC POP HL OR A JR Z,PART ;good write LD DE,NOSPC CALL PSTNG JP CPM ; partially full buffer PART: LD C,ACK CALL UDOUT LD A,(LAST) AND A JR NZ,GTLST1 CALL UDIN ; if hl equals buff (ie, nothing in buff), close file LD DE,BUFF LD A,H CP D JR NZ,GTLST0 LD A,L CP E JR Z,POST2 ; GTLST0: LD (HL),C JR POSTP GTLST1: LD B,A INC B GTLST2: CALL UDIN LD (HL),C INC HL CALL CONIN DJNZ GTLST2 ; POSTP: LD BC,BUFF+127 LD A,H cp B JR NZ,ONEMR LD A,L CP C JR Z,POST1 ONEMR: LD (HL),1ah INC HL JR POSTP ; write last block POST1: LD DE,FCB LD C,WRTF CALL BDOS OR A JR Z,POST2 LD DE,NOSPC CALL PSTNG JP CPM ; POST2: CALL UDIN LD DE,FCB LD C,CLSF CALL BDOS INC A JP NZ,CPM LD DE,WRTPROT CALL PSTNG JP CPM ; CONIN: IN A,(ACON) ;read from kbd AND 1 RET Z ; no kbd input IN A,(ADAT) CP 3 JP Z,CPM RET UDIN: CALL CONIN IN A,(BCON) AND 1 JR Z,UDIN ;no udrv output IN A,(BDAT) LD C,A CP ACK CALL Z,PRACK CP NACK CALL Z,PRNACK RET CONOUT: IN A,(ACON) ;send to screen BIT 2,A JR Z,CONOUT LD A,C OUT (ADAT),A RET UDOUT: IN A,(BCON) ;send to udrive BIT 2,A JR Z,UDOUT LD A,C OUT (BDAT),A RET ; PRACK: PUSH DE LD DE,ACKMSG CALL PSTNG POP DE RET ACKMSG: DB 'ACK',CR,LF,0 ; PRNACK: PUSH DE LD DE,NACKMSG CALL PSTNG POP DE RET NACKMSG: db 'NACK',CR,LF,0 ; SFN: LD DE,FNMSG CALL UDSTNG RET FNMSG: DB '@a ' FNMG1: DB 'NNNNNNNN.TTT',0 ; ; print content of (A) in hex ; PHEX: PUSH AF RRCA RRCA RRCA RRCA CALL PNIB POP AF CALL PNIB RET ; PNIB: AND 0fh CP 10 JR NC,PN0 ADD A,'0' JP PN1 PN0: ADD A,'A'-10 PN1: LD C,A CALL CONOUT RET ; PSTNG: LD A,(DE) CP 0 RET Z LD C,A PS1: IN A,(ACON) BIT 2,A JR Z,PS1 LD A,C OUT (ADAT),A INC DE JR PSTNG ; UDSTNG: LD A,(DE) CP 0 RET Z LD C,A UDS1: IN A,(BCON) BIT 2,A JR Z,UDS1 LD A,C OUT (BDAT),A INC DE JR UDSTNG ; FCB: DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0 ; RDMSG: DB CR,LF,'Reading ',0 SPACE: DB ' ',0 RECMSG: DB 'h 32b records plus ',0 NDMSG: DB 'h bytes.',CR,LF,0 NODIRSPC: DB 'No directory space.',0 NOSPC: DB 'Out of file space.',0 WRTPROT: DB 'Write protected.',0 BUFF: DS 128 DS 60 STACK: EQU $ END