;           RECEIVE
;
;        Nick Kennedy
;
;          11/15/86
;
; This program is intended to receive
; and run binary files via the 
; joystick (PIA) port.
;
; This part of the program creates 
; the cassette boot file.
;
NORECS: EQU [RECORD-START+127]/128
FLEN:   EQU NORECS*128
;
        ORG $4000
;
        PROC
CASFN:  DB 'C:', $9B
RUNCS:  LDX #$40 ; IOCB #4
        LDA #3 ; Open
        STA ICCOM,X
        LDA #HIGH CASFN
        STA ICBAH,X
        LDA #LOW CASFN
        STA ICBAL,X
        LDA #8
        STA ICAX1,X
        LDA #%10000000; Short IR gaps
        STA ICAX2,X
        JSR CIOV
        BPL :OK1
        STY $600
        RTS
;
; Now, put the entire file:
;
:OK1:   LDX #$40
        LDA #$B
        STA ICCOM,X
        LDA #HIGH STRT
        STA ICBAH,X
        LDA #LOW STRT
        STA ICBAL,X
        LDA #HIGH FLEN
        STA ICBLH,X
        LDA #LOW FLEN
        STA ICBLL,X
        JSR CIOV
        BPL :OK2
        STY $600
        RTS
;
:OK2:   LDA #$C ; Close IOCB
        STA ICCOM,X
        JSR CIOV
        BPL :OK3
        STY $601
;
:OK3:   RTS ; Back to DOS
;
	EPROC
;
; System Equates:
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
ICAX2:  EQU $34B
RTCLOK: EQU $14
BEEP:   EQU $FD
CONSOL: EQU $D01F
ZLOAD:  EQU $CB ; Z-page pointer L=2
;

STRT:   LOC $700 ; Cassette start
;
; Put Cassette header bytes:
;
LDADR:  DB $FF, LOW NORECS, LOW LDADR, HIGH LDADR
;
        DB LOW INIT1, HIGH INIT1
; Refer. to OS manual pg 166 and
; De Re Atari pg c-7/8:
;
START:  LDA #$3C ; Off motor
        STA $D302 ; (PACTL)
        LDA #LOW [RECORD+1]
        STA $237 ; (MEMLO)
        STA $E ; (APPMHI)
        LDA #HIGH [RECORD+1]
        STA $238
        STA $F
        LDA #LOW INIT
        STA $A ; (DOSVEC)
        LDA #HIGH INIT
        STA $B ; (DOSVEC)
        CLC ; indicate boot success
        RTS ; End of init.
INIT1:  RTS ; No boot continuation.
ENDL:   DS 1
ENDH:   DS 1
PLACE:  DS 1
TIMER:  DS 1 ; My timeout timer
FLAG:   DS 1 ;
;
;            STRINGS:
KYBD:   DB 'K:',$9B
PMPT1:  DB 'Input Filespec.  Example: D2:FILE',$9B
BSTMSG: DB 'Bad status on opening file.', $9B
NTLF:   DB 'Header error - not a load file.', $9B
;            INITIALIZE
;
INIT:   LDA #0 ; Clear Run/Init adr.
        STA $2E0
        STA $2E1
        STA $2E2
        STA $2E3
        JSR OPENK
        LDA #$9B
        JSR PUTBYT
        LDA #$9B
        JSR PUTBYT
        PRINTS PMPT1
        LDA #$9B
        JSR PUTBYT
;
; Stash cursor position:
;
        LDA $54
        PHA
        LDA $55
        PHA
        LDA $56
        PHA
GETRK:  JSR GETK
        CMP #$9B
        BEQ GREC
        JSR PUTBYT
        JMP GETRK
GREC:   PLA
        STA $56
        PLA
        STA $55
        PLA
        STA $54
        LDA #$1F ; CURSOR right
        JSR PUTBYT
        LDA #$1E ; left
        JSR PUTBYT
        LDA #13
        STA ICAX1 ; Forced read
        LDA #HIGH RECORD
        STA ICBAH
        LDA #LOW RECORD
        STA ICBAL
        JSR GETREC ; Get filename.
        PRINTS RECORD ; Echo it.
        LDA #12
        STA ICAX1
        JSR CLOSK ; Close #1.
;
; Send the filespec to the other 800:
;
        PROC
        JSR TINIT
        LDY #0
:LOOP:  LDA RECORD,Y ; Get byte
        JSR TLOOP ; Send it
        LDA RECORD,Y ; again to check
        CMP #$9B ; For EOL
        BEQ :DUN
        INY ; Next byte
        BNE :LOOP ; Forced branch
;
; Get ready to receive acknowledge:
;
:DUN:   JSR RINIT
        JSR RLOOP ; Get status
        BNE :GOOD
        PRINTS BSTMSG
        JMP INIT
:GOOD:  JSR RLOOP ; check header byts
        CMP #$FF
        BNE :BADHD
        JSR RLOOP
        CMP #$FF
        BEQ :GDHD
:BADHD: PRINTS NTLF ; Not load file
        JMP INIT
:GDHD:  JSR RLOOP ; Get load address
        STA LOAD+1
        STA $605 ;**********
        STA $607
        JSR RLOOP
        STA LOAD+2
        STA $606 ;***********
        STA $608
        JSR RLOOP ; Get end address
        STA ENDL
        JSR RLOOP
        STA ENDH
:RBYTE: LDY #0 ; Dummy index.
        JSR RLOOP ; Get file byte.
LOAD:   STA RECORD ; (Dummy address)
        LDA LOAD+2
        CMP ENDH
        BNE :NOTEQ
        LDA LOAD+1
        CMP ENDL
        BNE :NOTEQ
        JMP :SEGDUN ; Segment done
:NOTEQ: INC LOAD+1 ; Increment load
        INC $607;**************
        BNE :RBYTE ; address.
        INC LOAD+2
        INC $608 ;**************
        JMP :RBYTE
:SEGDUN LDA $2E2 ; Check init adr.
        BNE :INIT ; No init if = 0.
        LDA $2E3
        BEQ :RDY
:INIT:  LDA $2E2 ; (:INIT, not INIT)
        STA :GO+1 ; Set up JSR adr
        LDA $2E3
        STA :GO+2
:GO:    JSR HELL ; HELL is dummy ADR.
:RDY:   JSR JIF2 ; Stall 2 jiffies
        JSR TINIT
        JSR TLOOP ; Send any byte.
        JSR RINIT
        JSR RLOOP ; EOF?
        BEQ :RUN ; Yes
        JMP :GDHD
;
:RUN:   LDA $2E0
        BNE :DORUN
        LDA $2E1
        BNE :DORUN
:RUNN:  JSR HECK ; HECK is a dummy
:DORUN: LDA $2E0 ; if there's a run
        STA :RUNN+1 ; address, else
        LDA $2E1 ; we restart.
        STA :RUNN+2
        JMP :RUNN
        RTS ; In case it comes back
        
	EPROC
;
; JIF2: Stall 2 jiffies waiting to
; be sure the other guy gets into
; receive mode.
;
JIF2:   LDA RTCLOK
        STA PLACE
        INC PLACE
        INC PLACE
JIF2A:  LDA RTCLOK
        CMP PLACE
        BNE JIF2A
        RTS
;
JIF10:  LDA RTCLOK ; waste 10/60 sec.
        ADC #$A
        STA PLACE
JIF10A: LDA RTCLOK
        CMP PLACE
        BNE JIF10A
        RTS
;
; Subroutine to put record to E:
; (Have ICBAH/L loaded before entry)
; (Use MACRO PRINTS)
;
PUTREC: LDA #$80
        STA ICBLL
        LDX #0
        STX ICBLH
        LDA #9 ; Put record.
        STA ICCOM
        JSR CIOV
        RTS
;
; Subroutine to get a record from #0
; User set ICBAL/H.
;
GETREC: LDX #0
        LDA #5
        STA ICCOM
        LDA #$80
        STA ICBLL
        STX ICBLH
        JSR CIOV
        STY $600
        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
;
;
; 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
HELL:   PRINTS NOINI ; INIT =0
        PLA ; We shouldn't be here.
        PLA
        JMP INIT
HECK:   PRINTS RUNZRO ; RUN = 0
        PLA ; We shouldn't be here
        PLA
        JMP INIT
NOINI:  DB 'Went to INIT with INIT=0; ERROR!', $9B
RUNZRO  DB 'Went to RUN but RUN = 0; ERROR!', $9B
;

;
; The following is the transmit/
; receive portion of TALKP.
;
; 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)
;
;
;
DATA    DS 1 ; Store/send byte here
BITCT:  DS 1 ; Bit counter
;
;            STRINGS:
TOM:    DB 'TIMED OUT DURING BYTE TRANSFER', $9B
;
;            INITIALIZE
;
;
RINIT:  LDA #$FF ; Not ready.
        STA PORTA
        LDA #$9B
        JSR PUTBYT
        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
;
; 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 INIT ; 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 INIT ; 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
;
;  TRANSMIT section follows:
;
TINIT:  LDA #$0F ; Not ready/Not init
        STA PORTA
        LDA #LOW CTLDD
        STA PACTL ; Data direction
        LDA #%00000011
        STA PORTA
        LDA #LOW CTLRW
        STA PACTL ; Data register
        RTS
;

; RECORD is where I input my filename
; It takes no file space cause it's 
; at the end
;
OEND:   EQU *O
RECORD: END RUNCS
;
        

