;           RECEIVE
;
;        Nick Kennedy
;
;          11/15/86
;
; This program is intended to receive
; and run binary files via the serial
; input port.
;
; This part of the program creates 
; the cassette boot file.
;
        IF [RECORD-START+1] MOD 128
NORECS: EQU [RECORD-START+1]/128 + 1
        ELSE
NORECS: EQU [RECORD-START+1]/128
        ENDIF
;
        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 [RECORD-START+1]
        STA ICBLH,X
        LDA #LOW [RECORD-START+1]
        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:
IRQST:  EQU $D20E
B600LO EQU $CC ; for 600 baud
B600HI EQU $05
B192LO EQU $28 ; for 19.2K baud
B192HI EQU $0
SERIN:  EQU $D20D ; Data in register.
SEROUT: EQU $D20D ; Outgoing data here
IRQEN  EQU $D20E ; IRQ enable. 0=disable, 1=enable. Bit 5 is serial input.
;
POKMSK EQU $10 ; Shadow for above.
SKCTL:  EQU $D20F
SSKCTL: EQU $232 ; Shadow for above
SKSTAT: EQU $D20F ; Serial port stat.
SKRES:  EQU $D20A; Write resets above
AUDCTL  EQU $D208
VSERIN  EQU $20A; Serial input vector
VSEROR: EQU $20C ; Serial out ready.
VSEROC: EQU $20E ; Transmission cpt.
AUDF1:  EQU $D200
AUDF2:  EQU $D202
AUDF3:  EQU $D204
AUDF4:  EQU $D206
AUDC1:  EQU $D201
AUDC2:  EQU $D203
AUDC3:  EQU $D205
AUDC4:  EQU $D207
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, 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 ;
TVECT:  DS 2 ; Place for VSEROR
SIRF:   DS 1 ; Serial input rdy flag
SORF:   DS 1  ; Output ready flag
TCF:    DS 1 ; Transmission cpt flag
;
;            STRINGS:
IMHR:   DB 'I VE MADE IT THIS FAR!', $9B
KYBD:   DB 'K:'
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
MSFRE:  DB 'Data input frame error', $9B
SBOR:   DB 'Serial input over-run', $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.
;
; Set AUDCTL for 1.79 Mhz. into ch 3
; and ch 3 into ch 4:
;
        LDA #%00101000
        STA AUDCTL
;
;    Set baud rate
;
        LDA #B192LO
        STA AUDF3
        LDA #B192HI
        STA AUDF4
;
;
        LDA #$A0 ; Off Sound 1,2,3
        STA AUDC1
        STA AUDC2
        STA AUDC3
        LDA #$A8 ; On, channel 4
        STA AUDC4
;
; Set the interrupt vectors:
;
        SEI
        LDA #HIGH TINT
        STA VSEROR+1
        LDA #LOW TINT
        STA VSEROR
        LDA #HIGH RINT
        STA VSERIN+1
        LDA #LOW RINT
        STA VSERIN
        LDA #HIGH TCINT
        STA VSEROC+1
        LDA #LOW TCINT
        STA VSEROC
        CLI
;
; Initialize transmission done
; flag & input ready flag.
;
        LDA #0
        STA TCF
        LDA #$FF
        STA SIRF
;
; 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 #%11000111
        AND POKMSK ; Disable serial
        STA POKMSK ; bus IRQ's.
        STA IRQEN
        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
;
RINIT:  JSR JIF2 ; in case TCF fails.
        LDA TCF ; output complete?
        BNE RINIT ; No, wait.
        LDA #0
        STA SKCTL ; Init. POKEY
        LDA #$13
        STA SSKCTL
        STA SKCTL 
;
; Set the serial input IRQ vector to
; my service routine:
;
        SEI
        LDA #%00100000
        ORA POKMSK ; Enable input
        AND #%11100111;Disable output
        STA POKMSK ; and trans. cpt
        STA IRQEN
        CLI
        STA SKRES ; Reset status flgs
        RTS
;
; The program idles here while waiting for a SERIN interrupt:
;
RLOOP:  BIT SKSTAT ; Frame error?
        BMI GDSTM
        PRINTS MSFRE ; Yes
        PLA
        PLA
        JMP INIT
GDSTM:  BIT SKSTAT ; Over-run?
        BVS GDSTAT
        PRINTS SBOR ; Yes
        PLA
        PLA
        JMP INIT
GDSTAT: BIT SIRF ; Serial in ready?
        BMI RLOOP ; No
        LDA #$FF
        STA SIRF
        LDA SERIN ; Yes, read byte.
        RTS
;
; 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
;
;  TRANSMIT section follows:
;
TINIT:  JSR JIF10
        LDA #0
        STA SKCTL ; init POKEY
        STA SORF ; Output ready flag
        LDA #$23 ; KYBD scan and
        STA SSKCTL ; debounce on and
        STA SKCTL; bit 5 mode.
;
;       Enable interrupts:
;
        SEI
        LDA #%00010000 ;Send ready on
        ORA POKMSK
        AND #%11011111 ; Receive off.
        STA POKMSK
        STA IRQEN
        CLI
        RTS
;
; Transmit loop follows:
;
TLOOP:  PHA ; Save data
        LDA RTCLOK ; set up time out
        SBC #$A ; 10 jiffies limit
        STA PLACE
TLOOP1: LDA RTCLOK
        CMP PLACE ; Timed out?
        BNE TLOOP2 ; No.
        PRINTS TLPTO ; Yes
        PLA ; Clean off return adr
        PLA
        PLA ; And data
        JMP INIT ; Start over
TLOOP2: LDA SORF ; Ser. out ready?
        BMI TLOOP1 ; No.
        PLA ; Get data back
        STA SEROUT; Yes, send byte.
        LDA #$FF ; Not rdy flag.
        STA SORF
        STA TCF ; Trans. not cpt.
        SEI
        LDA #%00001000; Enable IRQ
        ORA POKMSK ; for trans. cpt.
        STA POKMSK
        STA IRQEN
        CLI
        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
;
;       Transmit interrupt routine:
;
TINT:   CLI
        LDA #0 
        STA SORF ; Output rdy flag
        STA CONSOL ;****************
        PLA
        RTI
;
; Receive interrupt routine:
;
RINT:   CLI
        LDA #0
        STA SIRF
        PLA
        RTI
;
; Output transmission cpt routine:
;
TCINT:  SEI ; in case not already
        LDA #0 ; Output is complete.
        STA TCF
        LDA #%11110111 ; Off with IRQ
        AND POKMSK ; for trans. cpt.
        STA POKMSK
        STA IRQEN
        PLA
        CLI
        RTI
;
;
; 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
TLPTO:  DB 'TIMED OUT IN TLOOP!', $9B
;
; RECORD is where I input my filename
; It takes no file space cause it's 
; at the end
;
OEND:   EQU *O
RECORD: END RUNCS
;
        

