.PREL .IDENT BITBANG .INSERT BBEQU.ASM .DEFINE WASTE[TIME,%LAB]=[ MVI A,TIME %LAB: DCR A JRNZ %LAB] BANGER=99H ; BIT BANGER IO PORT ; ***** ; * ; * COMMAND TO READ BLOCK INTO MEMORY ; * GET variable ; * ; ***** GETC:: CALL TSTVFF# CALL TAPGET RST RSTFIN ; ***** ; * ; * LOAD PROGRAM INTO MEMORY ; * ; ***** LOADC:: LXI H,TEXT# ; HL=TEXT AREA START ADDR CALL TAPGET SHLD TXTUNF# ; SET NEW TXTUNF JMP CLRSCR# ; ENTER CLEAR TO END ; ***** ; * ; * READ BLOCK INTO MEMORY ; * HL=READ ADDRESS ; * ; ***** TAPGET: PUSH D DI ..SENW: CALL INCHAR ; AWAIT SENTINEL CHARACTER MOV A,C JRZ ..SENW CPI 0A5H JRNZ ..SENW LXI D,4000H ; DE=FEEDBACK STORE ADDR ..CHRL: PUSH D CALL INCHAR POP D JRZ ..DONE MOV M,C MOV A,C STAX D ; GIVE FEEDBACK ON SCREEN INX D ; BUMP FEEDBACK ADDR RES 4,D ; CONSTRAIN TO 4000H-4FFFH INX H JMPR ..CHRL ..DONE: EI POP D RET ; ***** ; * ; * SUBROUTINE TO INPUT A CHARACTER ; * RETURNS CHARACTER IN C ; * AND STATUS OF NONZERO UNLESS A TIMEOUT HAPPENED ; * IN WHICH CASE ZERO STATUS IS RETURNED ; * ; ***** INCHAR: LXI B,810H ; B=BIT CTR, C=TIMEOUT FACTOR ..SBW: CALL INBIT ; AWAIT START BIT JRZ ..GETL DCR C ; NOT YET - DCR TIMEOUT JRNZ ..SBW ; IF COUNTED DOWN RET ; RETURN ZERO SET ..GETL: CALL INBIT RRC ; BIT GOT TO CY RARR C ; SHIFT INTO C HO DJNZ ..GETL ; NOW FALL INTO INBIT TO EAT THE STOP BIT INBIT: IN BANGER ; WAIT TILL WE GET A TRANSITION MOV E,A ..INBW: IN 15H ; CHECK FOR ABORT ANA A JNZ INIT0# ; HALT SET? IN BANGER XRA E RRC JRNC ..INBW WASTE 30 ; WAIT UNTIL SAMPLE POINT IN BANGER XRA E ; COMPARE TO OLDER STUFF ANI 1 RZ ; 0 IF TRANSITION HAPPENED WASTE 29 ; ELSE WAIT UNTIL MIDDLE OF NEXT CYCLE INR A ; RETURN VAL OF 1 RET ; ***** ; * ; * COMMAND TO WRITE OUT THE PROGRAM ; * ; ***** SAVEC:: PUSH D LHLD TXTUNF# LXI D,TEXT# ; DE=START ANA A DSBC D XCHG ; HL=ADDR,DE=SIZE JMPR SAVEE ; ***** ; * ; * COMMAND TO WRITE OUT A BLOCK OF WORDS ON TAPE ; * PUT variable,#words ; * ; ***** PUTC:: CALL TSTVFF# ; GRAB A VARIABLE PUSH H TSTCC COMMA,BADSAV RST RSTEXP ; GET NUMBA OF BYTES MOV A,H ; REJECT BIZARRE VALUES ORA L ; LIKE ZERO JZ QHOW# BIT 7,H ; OR NEGATIVE VALUES JNZ QHOW# DAD H ; CONVERT WORDS TO BYTES XCHG ; COUNT=DE XTHL ; STK=SCAN, HL=START SAVEE: DI CALL LEADER ; WRITE OUT LEADER MVI C,0A5H ; WRITE SENTINEL CALL OUTBYT CALL WRBLOC ; AND DATA BLOCK CALL LEADER ; THEN TRAILER EI POP D RST RSTFIN BADSAV: JMP QWHAT# ; ***** ; * ; * SUBROUTINE TO WRITE OUT BLOCK OF BYTES ; * HL=LIST, DE=# OF BYTES ; * ; ***** WRBLOC: ..BYTL: MOV C,M CALL OUTBYT INX H DCX D MOV A,D ORA E JRNZ ..BYTL RET ; ***** ; * ; * WRITE OUT A BYTE ONTO TAPE ; * ; * THIS ROUTINE IS TIME SENSITIVE! CHANGE CAREFULLY! ; * ; ***** OUTBYT: CALL WRZERO ; WRITE START BIT WASTE 19 ; FINISH START BIT MVI B,8 ; WRITE OUT 8 BITS ..WRL: RRCR C ; SHIFT NEXT BIT TO CY JRC ..WR1 ; BRANCH ON BIT VALUE CALL WRZERO ; THIS GUY ZERO WASTE 19 JMPR ..WRE ..WR1: ; WRITE ONE BIT CALL WRONE WASTE 42 ..WRE: DJNZ ..WRL ; LOOP TILL BYTE DONE CALL WRONE ; WRITE STOP BIT WASTE 43 RET ; SUBROUTINE TO WRITE OUT 3 SECONDS WORTH OF LEADER LEADER: LXI B,3600 ..LDR1: WASTE 43 CALL WRONE DCX B MOV A,B ORA C JRNZ ..LDR1 WASTE 42 RET ; SUBROUTINE TO WRITE 1 HALF CYCLE OF A ONE BIT ; 1/1200 SEC WRONE: OUT BANGER WASTE 46 OUT BANGER RET ; SUBROUTINE TO WRITE 1 HALF CYCLE OF A ZERO BIT ; 1/2400 SEC WRZERO: OUT BANGER WASTE 23 OUT BANGER RET .END