; 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