;            TALKP
;
;        Nick Kennedy
;
; A program to send data between two
; Atari 800 computers using the PIA's
; (joystick ports).
;

; System Equates:
PACTL:  EQU $D302
;
CTLRW:  EQU %00111100 ; to R/W port
CTLDD:  EQU %00111000 ; to write data
; direction. (0=input; 1=output)
;
PORTA:  EQU $D300
;
; For STICK 0, bits 0-3 equal pins
; 1-4. (8 is ground)
;
;   PINS:
;
;
;  1 2 3 4 5   ; View of jack on
;   6 7 8 9    ; console.
;
; NOTES:
;
; Pin 1 is data.
; Pin 2 is Transmitter status.
; (DATA READY or DR) (0 = READY).
; Pin 3 is Receiver status.
; (RECEIVER READY or RR) (0 = READY).
;
; Initialization: Before each byte
; sent/received all out lines are 
; made high. Transmitter makes sure
; RR is high, then sets DATA lo. 
; Receiver watches for DR high AND
; Data lo, then is freed to set RR
; lo (ready). Transmitter is then
; free to put data and set DR lo (rdy)
;
;
CH:     EQU $2FC ; Keyboard code here
CIOV:   EQU $E456
ICCOM:  EQU $342
ICBAL:  EQU $344
ICBAH:  EQU $345
ICBLL:  EQU $348
ICBLH:  EQU $349
ICAX1:  EQU $34A
RTCLOK: EQU $14
BEEP:   EQU $FD
CONSOL: EQU $D01F

;
        ORG $4000
PLACE:  DS 1
TIMER:  DS 1 ; My timeout timer
FLAG:   DS 1 ;
DATA    DS 1 ; Store/send byte here
BITCT:  DS 1 ; Bit counter
;
;            STRINGS:
MODE:   DB 'PRESS START FOR RECEIVE',$9B
MODE2:  DB 'PRESS SELECT FOR TRANSMIT',$9B
MSG1:   DB 'NOW IN RECEIVE MODE.',$9B
MSG2:   DB 'TRANSMIT MODE; "CONTROL-A" to RECEIVE',$9B
MSG3:   DB 'PRESS OPTION TO EXIT', $9B
MSG5:     DB 'TRANSMIT CONTROL-D FOR MENU', $9B
TOM:    DB 'TIMED OUT DURING BYTE TRANSFER', $9B
KYBD:   DB 'K:', $9B
MSG4:   DB 'TRANSMITTER HAS EXITED PROGRAM', $9B
;
;
;            INITIALIZE
;
INIT:   LDA #125 ; Clear screen.
        JSR PUTBYT
INIT1:  LDA #$FF ; Trans. and Rcvr
        STA PORTA;   Not ready
        LDA #$9B
        JSR PUTBYT
        LDA #$9B
        JSR PUTBYT
        PRINTS MODE
        LDA #$9B
        JSR PUTBYT
        PRINTS MODE2
        LDA #$9B
        JSR PUTBYT
        PRINTS MSG3
        LDA #$9B
        JSR PUTBYT
        PRINTS MSG5
        LDA #$9B
        JSR PUTBYT
        JSR OPENK
;
TORR:   JSR WAIT ; Get button choice
        CMP #6 ; START
        BEQ GRINIT
        CMP #5 ;  SELECT
        BEQ GTINIT ; Long branch
        CMP #3 ; OPTION
        BNE TORR
        RTS ; Choice was exit
;
;
; Transmit loop follows:
;
GTINIT: JSR TINIT ; Set up to XMT
TRANS:  JSR GETK ; get a byte
        PHA ; stash it
        JSR TLOOP ; send the byte
        PLA ; restore it
        CMP #'A'-$40 ; CONTROL-A?
        BEQ GRINIT ; Yes?  Switch
        CMP #'D'-$40 ; CONTROL-D?
        BNE DONTQ ; Don't quit
        LDA #125 ; Clean screen
        JSR PUTBYT
        JMP INIT1 ; EXIT to menu
DONTQ:  JSR PUTBYT ; No? Print it and
        JMP TRANS ; Get another.
;
; Receive loop follows:
;
GRINIT: JSR RINIT ; Set up to RCV
RCV:    JSR RLOOP ; Receive a byte
        CMP #'A'-$40 ; CTRL-A?
        BEQ GTINIT ; Yes? Switch!
        CMP #'D'-$40 ; CTRL-D
        BNE NQ ; Don't quit
        LDA #$9B
        JSR PUTBYT
        PRINTS MSG4 ; XMTR has exited
        JMP INIT1 ; EXIT to menu
NQ:     JSR PUTBYT ; No? Print it!
        JMP RCV ; and get another.
;
;
RINIT:  LDA #$FF ; Not ready.
        STA PORTA
        LDA #$9B
        JSR PUTBYT
        PRINTS MSG1
        LDA #LOW CTLDD ; Make PORTA
        STA PACTL ; be data direction
        LDA #%00000100 ; register.
        STA PORTA ; Made bit 2 input.
        LDA #LOW CTLRW ; Make PORTA
        STA PACTL ; be I/O port again
        RTS
;
;
; Wait for console button routine:
;
WAIT:   LDA CONSOL
        AND #7 ; 3 lo bits only.
        CMP #7
        BEQ WAIT
        RTS
;
; This subroutine receives a byte:
;
RLOOP:  LDA PORTA ; XMT initialized?
        AND #3 ; Get bits 0 and 1
        CMP #2 ; Data LO & DR HI?
        BNE RLOOP ; Keep checking
        LDA #7 ; Bit counter (0-7)
        STA BITCT
RLP3:   LDA #$FF - 4 ; clear bit 2
        STA PORTA ; (set RR ready)
RLP1:   LDA BITCT ; We don't time out
        CMP #7 ; if waiting for the
        BEQ SEVEN ; first bit.
        LDA RTCLOK ; But check on
        CMP TIMER ; later bits
        BNE NOTO ; No timeout
GOON:   PRINTS TOM ; timeout message
        PLA ; Clear return address
        PLA ; from stack.
        JMP INIT1 ; Goto menu
SEVEN:  LDA RTCLOK ; Set up timer for
        STA TIMER ; one to two jiff's
        INC TIMER
        INC TIMER
NOTO:   LDA PORTA ; check DR
        AND #2 ; Mask all but DR line
        BNE RLP1 ; DATA not ready
        ASL DATA
        LDA PORTA ; Read data
        AND #1 ; Mask non-data
        CLC
        ADC DATA ; add it to DATA
        STA DATA
        LDA #$0F
        STA PORTA ; RR not ready
RLP2:   LDA TIMER
        CMP RTCLOK
        BEQ GOON ;  Go on. (exit)
        LDA PORTA ; Check for DR not.
        AND #2
        BEQ RLP2 ; DR not set
        DEC BITCT ; Next bit
        BPL RLP3 ; Do 8 bits
        LDA DATA ; Take it home
        RTS
;
;
; This subroutine sends a byte out
; over the PIA line:
;
TLOOP:  STA DATA ; Store the byte
TLP4:   LDA PORTA ; Check rcvr status
        AND #4
        BEQ TLP4 ; Loop if ready.
        LDA #2 ; Set DR=1, DATA=0
        STA PORTA
        LDA #7 ;    Bit counter
        STA BITCT ; initialize
        LDA RTCLOK
        STA TIMER
        INC TIMER
        INC TIMER
TLP1:   LDA RTCLOK ; Check for time
        CMP TIMER ;waiting for RR.
        BNE TLP5 ; No timeout
TGOON:  PRINTS TOM ; timeout message
        PLA ; Clear return address
        PLA ; from stack.
        PLA ; Also clear data byte.
        JMP INIT1 ; Goto menu
TLP5:   LDA PORTA ; Receiver ready?
        AND #4 ; Bit 2 is RR line
        BNE TLP1 ; Not ready
        ASL DATA ; Knock left bit
        LDA #0 ; Into carry
        ADC #0 ; add carry to 0
        STA PORTA ; Put data/DR ready
TLP2:   LDA TIMER
        CMP RTCLOK
        BEQ TGOON ; Timed out
        LDA PORTA ; RCVR accept data?
        AND #4 ; RR line set?
        BEQ TLP2 ; Not yet
        LDA #$0F ; Data not ready.
        STA PORTA ; Tell RCVR
        DEC BITCT ; Count the bit
        BPL TLP1 ; 8 bits sent?
        RTS
;   Subroutine to put record to E:
; (Have ICBAH/L loaded before entry)
;
PUTREC: LDA #$80
        STA ICBLL
        LDX #0
        STX ICBLH
        LDA #9 ; Put record.
        STA ICCOM
        JSR CIOV
        RTS
;
; Subroutine to put byte to E:
; (Have byte in accumulator on entry)
;
PUTBYT: LDX #$B ; Put byte
        STX ICCOM
        LDX #0
        STX ICBLH
        STX ICBLL
        JSR CIOV
        RTS
;
;  TRANSMIT section follows:
;
TINIT:  LDA #$0F ; Not ready/Not init
        STA PORTA
        PRINTS MSG2
        LDA #LOW CTLDD
        STA PACTL ; Data direction
        LDA #%00000011
        STA PORTA
        LDA #LOW CTLRW
        STA PACTL ; Data register
        LDA #$FF
        STA CH ; Clear keyboard
        RTS

;
; A routine to get one byte from 
; IOCB #0 (assumed to be E:):
;
GETBYT: LDX #0
        STX ICBLL
        STX ICBLH
        LDA #7
        STA ICCOM ; Get bytes.
        JSR CIOV
        RTS
;
; OPEN KEYBOARD, IOCB #1
;
OPENK:  LDX #$10
        LDA #3
        STA ICCOM,X
        LDA #4 ; Read
        STA ICAX1,X
        LDA #HIGH KYBD
        STA ICBAH,X
        LDA #LOW KYBD
        STA ICBAL,X
        JSR CIOV
        RTS
CLOSK:  LDX #$10 ; Close it.
        LDA #$C
        STA ICCOM,X
        JSR CIOV
        RTS
;
GETK:   LDX #$10 ; Get one byte from 
        LDA #$7 ;  keyboard.
        STA ICCOM,X
        LDA #0
        STA ICBLL,X
        STA ICBLH,X
        JSR CIOV
        RTS
;
        END INIT
;
        
