; Uploaded to simtel-20 by Ralph Hyre (ralphw@c.cs.cmu.edu) ; Sent to Ralph by Chris Peck (chris@bingvaxb.bitnet) ; You will need one of the follwing items to use these drivers: ; the PCPI OEM package (bucks involved - order from PCPI) ; the assembled output of the PCPI OEM package assembler. ; (this will be made available here as soon as I can assemble it) ;************************************ ;ROUTINE: GAMEPRT.A65 ;PURP: USE THE GAME I/O PORT FOR A SERIAL OUTPUT PORT ; ; 06/09/83 CREATED (FPM) ; 06/30/83 ADDED PARITY GENERATING ROUTINE ; TRUE: .EQU 0FFH FALSE: .EQU 0 ;************************ USER EQUATES *************************** ;BE SURE TO SET ONLY ONE BAUD TRUE BAUD300: .EQU FALSE ;TRUE=300 BAUD BAUD600: .EQU FALSE ;TRUE=600 BAUD BAUD1200: .EQU TRUE ;TRUE=1200 BAUD BAUD2400: .EQU FALSE ;TRUE=2400 BAUD BAUD4800: .EQU FALSE ;TRUE=4800 BAUD BAUD9600: .EQU FALSE ;TRUE=9600 BAUD PUSHBUTTON: .EQU 0 ;BUSY INPUT LINE ->SET TO 0, 1 OR 2 ANNUNCIATOR: .EQU 0 ;DATA OUTPUT LINE ->SET TO 0, 1, 2 OR 3 STOPBITS: .EQU 1 ;NUMBER OF STOP BITS ->SET TO 1 OR 2 PARITY: .EQU FALSE ;TRUE=GENERATE PARITY FALSE=NO PARITY ODD: .EQU TRUE ;TRUE TO GENERATE ODD PARITY EVEN: .EQU FALSE ;TRUE TO GENERATE EVEN PARITY ;If parity if set to TRUE either ODD or EVEN must be TRUE!!! ;****************************************************************** ;DISCUSSION: ;This experimental driver can be used to output bytes to some RS-232 ;compatible devices. Specifically it has been tested on a QUME Sprint 5/45, ;a Chyron VP-1 character generator and a CVC Intelligent controller. For ;proper operation only 3 lines are necessary. One is for sending the ;characters, one for a handshake line, and finally a signal ground. ;For this discussion assume a QUME serial printer is to be used. ;PIN CONFIGURATION: See figure 16 ->Apple II Reference Manual pp.100 ;------------------------------------------------------------------- ; SIGNAL NAME GAME I/O CONNECTOR QUME PRINTER ;------------------------------------------------------------------- ; Ground Pin #8 (Gnd) Pin #7 ; RTS(Clear to Send) Pin #2 (PB0) Pin #4 ; RXD(Receive Data) Pin #15(AN0) Pin #3 ;-------------------------------------------------------------------- ;The QUME will accept characters until its buffer is full, at which time ;it will lower the RTS line to signal the sending computer showing it is ;is no longer ready for characters. This line is wired to push-button ;#0 of the Game I/O connector. When this line goes low, the hi bit of ;pushbutton #0 is reset(0). The output routine will wait until this bit ;is high(1) before outputting a character. ; ;Character output is accomplished by breaking each character into ;a start bit, its normal 8 bits, and a stop bit. Annunciator #0 ;is used here (however any of the annunciators would work). First a ;start bit(Space or +5) is sent by turning on AN0(LDA $C059). ;Then each bit of the character is sent starting with the LSB. ;If the bit is a 1, the annunciator is turned off and is it is a 0 ;it is turned on. Finally 1(or 2) stop bits(Mark or 0 volts) are sent by ;turning off AN0(LDA $C058). A software timing loop is implemented ;to control the speed of sending. Since the RS-232 standard is from ;+3 to +12 volts and -3 to -12 volts, many receiving devices will ;see the change from 0 to 5 volts (or 5 to 0 volts) as a change ;in state and read it as such. Some RS-232 receivers may, however, not ;recognize these signal levels, so you'll just have to experiment. ; ;["Editor's" note: you may get better results by using a the 1488 and 1489 ; line driver and receiver chips, which convert RS-232 <-> TTL levels. ; These chips also provide a measure of protection for your Apple.] ; ;Since the RS-232 standard allows for about a 2% error on the receiving ;end, slight timing differences from a clock crystal on the transmitting ;end can usually be ignored. The transmitting error for this driver ;is lower than 1.0%. The 300, 600, and 1200 baud rates were tested ;on a QUME printer and a Televideo 950 terminal. The 2400, 4800, ;and 9600 baud rates were tested on the Televideo, VP1 character ;generator, and CVC units. 9600 baud is the fastest rate possible ;with this algorithm. ; ;If parity is desired, first set the PARITY equate to TRUE. Then ; set either ODD or EVEN to true. Even parity makes the total number ;of 1-bits in the stream of bits even; ;odd parity makes the total ;number of 1-bits odd. Be sure to set the receiving device for the ;proper parity if it is enabled. ;GET EQUATES .NOLIST .INCLUDE DRVREQUS.A65 .LIST BUSYIN: .EQU 0C061H+PUSHBUTTON SPACE: .EQU 0C059H+(ANNUNCIATOR*2) MARK: .EQU 0C058H+(ANNUNCIATOR*2) BITNUMBER: .EQU 1+8+STOPBITS ;1START+8DATA+STOPBITS=NUMBER BITS TO SEND .IF PARITY AND ODD PARTYPE: .EQU 1 .ENDC .IF PARITY AND EVEN PARTYPE: .EQU 0 .ENDC ;TIMER VALUE TABLE: ;------------------------------------- ; BAUD RATE VALUE ;------------------------------------- ; 300 241 ; 600 120 ; 1200 59 ; 2400 29 ; 4800 14 ; 9600 6 ;------------------------------------- .IF BAUD300 TIMER: .EQU 241 ;300 BAUD TIMING VALUE .ENDC .IF BAUD600 TIMER: .EQU 120 ;600 BAUD TIMING VALUE .ENDC .IF BAUD1200 TIMER: .EQU 59 ;1200 BAUD TIMING VALUE .ENDC .IF BAUD2400 TIMER: .EQU 29 ;2400 BAUD TIMING VALUE .ENDC .IF BAUD4800 TIMER: .EQU 14 ;4800 BAUD TIMING VALUE .ENDC .IF BAUD9600 TIMER: .EQU 6 ;9600 BAUD TIMING VALUE .ENDC ;***************************************************************** BASEP0: .QUERY "ENTER BASE OF PAGE 0: " LENP0: .EQU 0 ;HEADER FOR RELOCATION TOP: .WORD 0 ;IF THIS WORD IS 0 THEN ; RELOCATABLE DRIVER ; AND A RELOCATING BIT MAP IS EXPECTED ;ELSE ; THE DRIVER STORED WHERE INDICATED .WORD ((BOTTOM-TOP)+0FFH) AND 0FF00H ;LENGTH OF THIS CODE ; TO NEXT PAGE BOUNDRY .BYTE LENP0 ;THIS IS THE NUMBER OF PAGE 0 BYTES ; REQUIRED. IF ITS NO ZERO THEN A RELOCATING ; BIT MAP IS EXPECTED FOR PAGE 0 .BYTE 0 ;TAG FIELD .WORD 14H ;DEVICE NUMBER (14=CHARACTER DEVICE 4=UL1:) .WORD 1 ;NUMBER OF DEVICES THIS DRIVER WILL SERVICE .WORD INITENTRY ;INIT ENTRY POINT .WORD INENTRY ;INPUT ENTRY POINT .WORD OUTENTRY ;OUTPUT ENTRY POINT .WORD OTHERENTRY ;OTHER ENTRY POINT .WORD POLLENTRY ;POLL ENTRY POINT .WORD 2 ;VERSION NUMBER .IF BAUD300 NAME: .BYTE 13,"GAME PORT 300" ;NAME OF DRIVER .ENDC .IF BAUD600 NAME: .BYTE 13,"GAME PORT 600" ;NAME OF DRIVER .ENDC .IF BAUD1200 NAME: .BYTE 14,"GAME PORT 1200" ;NAME OF DRIVER .ENDC .IF BAUD2400 NAME: .BYTE 14,"GAME PORT 2400" ;NAME OF DRIVER .ENDC .IF BAUD4800 NAME: .BYTE 14,"GAME PORT 4800" ;NAME OF DRIVER .ENDC .IF BAUD9600 NAME: .BYTE 14,"GAME PORT 9600" ;NAME OF DRIVER .ENDC ;************************************* ;ROUTINE: INITENTRY ;PURP: INITIALIZE ;ENTRY: NONE ;USED: ALL ;************************************* INITENTRY: RTS ;*********************************** ;ROUTINE: INENTRY: ;PURP: INPUT A CHARACTER ;ENTRY: Y = n0 ; X = Cn ; WHERE n IS THE SLOT NUMBER ;EXIT: A = CHARACTER ;USED: ALL ;*********************************** INENTRY: RTS ;RETURN TO CALLER ;*********************************** ;ROUTINE: OUTENTRY ;PURP: OUTPUT A CHARACTER TO THE DEVICE ;ENTRY: A = CHARACTER ; Y = n0 ; X = Cn ; WHERE n IS THE SLOT NUMBER ;EXIT: NONE ;USED: ALL ;************************************ OUTENTRY: BIT BUSYIN ;READ PUSH-BUTTON (BUSY INPUT) BPL OUTENTRY ;NOT READY IF VOLTAGE IS LOW - SO WAIT ;***THANKS TO BOB SANDER-CEDERLOF OF S-C SOFTWARE FOR THE PARITY ROUTINE*** .IF PARITY ;ON ENTRY A=CHAR LDX #PARTYPE ;1=ODD 0=EVEN ASL A ;SHIFT PARITY POSITION OUT PHA ;SAVE SHIFTED CHARACTER $1: BPL $2 ;IF NEXT BIT=0, DON'T COUNT INX ;IF NEXT BIT=1, COUNT IT $2: ASL A ;SHIFT IN NEXT BIT BNE $1 ;IF ANY REMAINING BITS = 1 TXA ;GET COUNT OF 1-BITS LSR A ;EVEN/ODD BIT OF COUNT IN TO CARRY PLA ;ORIGINAL CHAR BUT SHIFTED ROR A ;SHIFT PARITY BIT INTO BIT 8 .ENDC ;ON EXIT A=CHAR WITH PARITY PHP ;SAVE PROCESSOR STATUS(W/INTERPT STAT) SEI ;DISABLE INTERRUPTS ALWAYS LDY #BITNUMBER ;# BITS TO SEND CLC ;SET UP FOR START BIT(ALWAYS SPACE) $3: PHA ;3\ ;SAVE CHAR BCS $4 ;2 \ ;1-BIT, SEND MARK LDA SPACE ;4 \ ;0-BIT, SEND SPACE BCC $5 ;2 > =13 cycles $4: LDA MARK ; / ;MARK $5: LDA #TIMER ;2/ ;TIMING LOOP COUNTER $6: PHA ;3\ NOP ;2 \ PLA ;4 >=14xTIMER cycles SBC #1 ;2 / BNE $6 ;3/ PHA ;3\ PLA ;4 \ PLA ;4 \ ;GET CHAR (CARRY IS SET FOR STOPS) ROR A ;2 / =18 cycles;NEXT BIT INTO CARRY DEY ;2 / BNE $3 ;3/ ;SEND NEXT BIT PLP ;RESTORE PROCESSOR STATUS(&INTERRUPTS IF ANY) RTS ;1200 BAUD TIMING ;AVERAGE BIT TRANSMISSION TIME (1200)-> 13+(14x59)+18=857 cycles/bits ;EXACT TIMING IS 1.023E6/1200=852 cycles/bit +/- 2% (+/-8 cycles) ;300 BAUD TIMING ;AVERAGE BIT TRANSMISSION TIME (300)-> 13+(14x241)+18=3405 cycles/bit ;EXACT TIMING IS 1.023E6/300=3410 cycles/bit +/- 2% (+/-34 cycles) ;*********************************** ;ROUTINE: OTHERENTRY ;PURP: HANDLE OTHER COMMANDS ;ENTRY: A = OTHER COMMAND ; X = N0 ; Y = CN ;EXIT: A = ERROR CODE ;USED: ALL ;*********************************** OTHERENTRY: CMP #0 BEQ OUTSTAT ;BRANCH IF OUTPUT STATUS COMMAND CMP #1 BEQ INSTAT ;BRANCH IF INTPUT STATUS COMMAND CMP #2 BEQ VIDEOON ;BRANCH IF VIDEO ON COMMAND CMP #3 BEQ APLEON ;BRANCH IF APPLE ON COMMAND CMP #4 BEQ WIDTH ;BRANCH IF WIDTH COMMAND CMP #SNDNAMECMD BEQ SENDNAME ;BRANCH IF SEND NAME COMMAND ;ERROR BAD COMMAND LDA #0FFH ;ELSE ERROR RTS OUTSTAT: ;TEST IF THE DEVICE IS READY TO SEND ANOTHER CHARACTER BIT BUSYIN ;CHECK INPUT STATUS BPL NOTRDY ;BIF NOT READY TO SEND BMI RDY ;BIF READY TO SEND INSTAT: ;TEST IF THE DEVICE HAS A CHARCTER TO INPUT ;SHOW NOT READY AT ALL TIMES NOTRDY: LDA #0 RTS RDY: LDA #0FFH RTS VIDEOON: ;DO SOMETHING TO TURN ON YOUR VIDEO ; THIS IS PROBABLY NOTHING UNLESS THIS IS A CONSOLE DEVICE RTS APLEON: ;DO SOMETHING TO TURN ON THE APPLE VIDEO ON ; THIS IS PROBABLY NOTHING UNLESS THIS IS A CONSOLE DEVICE RTS WIDTH: ;RETURN THE WIDTH OF THIS DEVICE LDA #80 ;80 COLUMNS ? RTS SENDNAME: ;SEND THE NAME COMMAND LDA NAME ;GET LENGTH STA CNT ;SAVE AS COUNT JSR WR1Z80BYTE ;SEND IT TO HOST LDA #1 STA IDX LDA CNT CLC BEQ EXIT $LP: LDX IDX LDA NAME,X ;GET NEXT CHARACTER JSR WR1Z80BYTE INC IDX DEC CNT BNE $LP ;CONTINUE UNTIL ALL BYTES ARE SENT EXIT: BCS ERRXIT LDA #0 RTS ERRXIT: TAY BNE RET ERROR: LDA #0FFH RET: RTS ;*********************************** ;ROUTINE: POLLENTRY ;PURP: HANDLE POLLING, THIS ENTRY POINT ; IS CALLED PERIODICALY WHILE THE APPLE IS ; WAITING FOR A COMMAND FROM THE Z-80. THIS ; CODE SHOULD BE VERY SHORT AS THE Z-80 IS ; IGNORED WHILE THIS CODE IS BEING EXECUTED ;ENTRY: NONE ;EXIT: NONE ;USED: ALL ;*********************************** POLLENTRY: RTS ;TEMPORARY DATA IDX: .BLOCK 1 ;TEMPORARY CNT: .BLOCK 1 ;TEMPORARY BOTTOM: .END