	PROCESSOR 6502
        LIST    ON

	ORG	$0800
; constants
COUT1	EQU	$FDED
CLEAR	EQU	$FC58
KEYBOARD	EQU	$C000
KBCLEAR	EQU	$C010
COLUM80 EQU	$C300	; assume 80 column card in slot 3
PRIMMON EQU 	$C058
SECMON  EQU	$C059


WINDOWTOP EQU	34	; input window top
VERTLOC	EQU 	37	; vertical location
NCOUNT 	EQU	$35	; counter used in bit out and in routines
BELL 	EQU	$438	; bell counter  0 = don't ring bell
BAUDCONST EQU	$3B8
STATUS 	EQU	$4B8	; status saved at init time
BYTE	EQU	$5B8	; data byte
NO	EQU	$6F8	; slot < 4
PARITY	EQU	$778	; parity accumulator
SLOTADDRESS EQU	$C2	; serial interface slot address
SLOT	EQU 	2	; hard code slot

; flow for Apple IIe Teletype emulation
START:
	JSR	COLUM80		; set 80 colum video mdoe (assumes prescence of 80 column card)
	LDA	SECMON		; use correct monitor
	LDA	#16
	STA	WINDOWTOP	; new top
	LDA	#25		; home 
	JSR	COUT1		;

; serial output  (110 baud)
; 7F8 and X = 0xCN  (where N = slot number)
; Y = 0xN0 (where N = slot number) - this is used to access device I/O space on card
; 6F8/N0 - where N = slot number
; 778/PARITY = random - used as scratch pad
; 3B8,X/BAUDCONST  where X = N (slot number) = baud rate constant  (B0 for 110)
; 4B8,X/STATUS where X = N (slot number) = 
; 5B8,X/BTYE
; initialize serial params

	LDX	#SLOTADDRESS
	LDA	#$AF
	STA	BAUDCONST,X
	LDA	#$6		; status - no parity, no checksum
	STA	STATUS,X
	LDA	#$0
	STA	BELL,X		; don't ring ring bell 

; main loop	
; set 80 column mode and clear screen
GETNEXTCHAR:
	LDX	#SLOTADDRESS
	LDY	#$20		; slot << 4
	STY	NO
GETNEXTCHARLOOP1:
	LDA	#100		; bell delay counter
	STA	NCOUNT
;
; buzz speaker for a bit while polling
;
GETNEXTCHARLOOP2:
; check for keyboard input?
	LDA	KEYBOARD
	BMI	KEYIN

; check for serial input?
	LDA 	$C081,Y		; serial input going low?
	BPL	SERIAL_START	; serial input check true - branch
; is bell sounding?
	LDA	BELL,X		; don't ring ring bell 
	BEQ	GETNEXTCHARLOOP2 ; if zero
; the bell is sounding -delay to create decent fequency
	DEC	NCOUNT	
	BNE	GETNEXTCHARLOOP2 ; nope, continue polling
; toggle bell until counter goes to zero
	LDA	$C030
	DEC	BELL,X
	JMP	GETNEXTCHARLOOP1 ; continue withl poll loop
;
; serial start bit detected
; X and Y are already initialized
;
SERIAL_START:
	JSR	GETSERIAL	; call serial input routine
	LDA	BYTE,X		; get byte read
	JSR	DISPLAYONSCREEN ; display it on the screen
	JMP	GETNEXTCHAR	; continue with poll loop

;
; read character from keyboard, display on screen and echo to serial port
; character from keyboard  in A
;
KEYIN:
	STA	KBCLEAR		; clear keyboard strobe
	STA	BYTE,X		; save byte in buffer
	JSR 	DISPLAYONSCREEN	; call display on screen

	LDX	#SLOTADDRESS	; set up regs for serial output
	LDY	#$20		; slot << 4
	STY	NO
	JSR	PUTSERIAL	; call serial output
	JMP	GETNEXTCHAR 	; return to getnextchar


; display character on screen (input reg A = character)
DISPLAYONSCREEN:
	CMP	#$8D		; CR return only returns cursor to column 0
	BEQ     DOS_CR
	CMP	#$87		; Bell Character?
	BEQ	DOS_RING_BELL 	; yes, branch to poll loop that rings bell
	JSR	COUT1
; return to caller
	RTS
;
; Need to flag to return to bell routine
;
DOS_RING_BELL
	LDA	#100	
	STA	BELL,X		; save bell ring count in buffer, signal bell ringing function to start
	RTS

DOS_CR:
	LDA	WINDOWTOP	; fetch text window top
	PHA			; save it
	LDA	VERTLOC		; fetch vertical location
	STA	WINDOWTOP	; and make current top of display

	LDA	#25		; home 
	JSR	COUT1		;
	PLA
	STA	WINDOWTOP	; restore old top of display
	RTS

; 7F8 and X = 0xCN  (where N = slot number)
; Y = 0xN0 (where N = slot number) - this is used to access device I/O space on card
; 6F8/N0 - where N = slot number
; 778/PARITY = random - used as scratch pad
; 438,X/BELL 
; 4B8,X/STATUS where X = N (slot number) = 
; 5B8,X/BTYE

; serial input (110 baud)
GETSERIAL:

;
	SEI
	LDA 	#$08
	STA 	NCOUNT
	LDY 	NO
I_WAIT_START:
	LDA 	$C081,Y			; read input, waiting for start bit
	BMI	I_WAIT_START

	LDA BAUDCONST,X
	LDY #$09
I_IWAIT:				;inner delay
	DEY
	BNE I_IWAIT
	SBC #$01
	BEQ I_GETBIT			; done delaying, branch to start getting data
	LDY #$0E
	BNE I_IWAIT

I_GETBIT:
	LDY NO
	LDA $C081,Y			; read input, waiting for start bit

	ROL
	ROR BYTE,X
	DEC NCOUNT			; all bits recieved?
	BEQ I_MOD

	LDA BAUDCONST,X			; fetch baud rate constant
	SEC
I_WAIT1:
	SBC #$01
	BEQ I_GETBIT
	LDY #$09
I_WAIT53:				; delay = 53X(BRATE-1) CYCLES
	DEY
	BNE I_WAIT53
	BEQ I_WAIT1

I_MOD:
 ; wait for stop bit before returning
	LDA $C081,Y
	BPL I_MOD
	RTS


; Hijacked from standard serial card ROMs
;
; serial output  (110 baud)

PUTSERIAL:
	SEI
	CLC			; clear carry
	PHP			; for second pass (after sending stop bits)
	SEC			; set carry indicating first pass and
	PHP			; save it for later on stack
	LDY #$09		; counting start bit - 9 bits
	STY NCOUNT		; save in COUNTER

	LDA #$00
	ASL BYTE,X		; 5B8 + X (CN) ???
O_NEXTBIT:
	ROR BYTE,X
	ROL			;  a bit
	ORA NO			; 
	TAY
O_STOP:
	SEC
	LDA $C080,Y		; output bit
	LDA BAUDCONST,X		; fetch baud rate delay
O_OUTER_DELAY:
	SBC #$1			; outer delay loop
	BEQ O_DELAY_DONE
	LDY #$09		; inner delay loop
O_INNER_DELAY:
	DEY			; 9 x (00 + 00)
	BNE O_INNER_DELAY	;
	BEQ O_OUTER_DELAY	;

O_DELAY_DONE:
	LDY #2			; 2 stop bits
	DEC NCOUNT		; count bits
	BNE O_NEXTBIT		; next bit

	PLP			; check flag set a beginning
	BCC O_DONE		; not set, all done

	STY NCOUNT		; save counter for stop bits
	SEC			; set up second stop bit
	ROL BYTE,X		; 5B8 + X (CN) ???
	LDA #1			; stop bits are always 1
	ORA NO
	TAY
	JMP O_STOP		; send stop bits
O_DONE:
	TAY
	RTS


