	PROCESSOR 6502
        LIST    ON

SLOT	EQU 	2	; hard code slot

	ORG	$0800
TRUE	EQU	$1
FALSE	EQU	$0
SHIFT   EQU	$1B
UNSHIFT EQU	$1F

; Moniter Functions
COUT1	EQU	$FDED
CLEAR	EQU	$FC58

; Hardware address
SLOTADDRESS EQU	$C0 + SLOT ; serial interface slot address
KEYBOARD	EQU	$C000
KBCLEAR	EQU	$C010
COLUM80 EQU	$C300	; assume 80 column card in slot 3
PRIMMON EQU 	$C058
SECMON  EQU	$C059

; zero page
WINDOWTOP EQU	34	; input window top
NCOUNT 	EQU	$35	; counter used in bit out and in routines
VERTLOC	EQU 	37	; vertical location


; video holes for peripheral storage
BAUDCONST EQU	$3B8
BELL	EQU	$438	; number of stop bits
OSHIFT 	EQU	$4B8	; output baudet shift status
ISHIFT	EQU	$538	; input baudet shift status
BYTE	EQU	$5B8	; data byte
NO	EQU	$6B8	; slot < 4

SLOTSAVE EQU	$7F8	; $CN where N = current active 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	#12
	STA	WINDOWTOP	; new top

	LDA	#25		; home 
	JSR	COUT1		;
; serial output  (110 baud)
; 3B8,X/BAUDCONST  where X = N (slot number) = baud rate constant  (B0 for 110)
; 4B8,X/OSHIFT = output baudet stream shifted 
; 538,X/ISHIFT = input baudet stream shifted
; 5B8,X/BTYE
; 6F8/N0 - where N = slot number
; 7F8 and X = 0xCN  (where N = slot number)
; initialize serial params

	LDX	#SLOTADDRESS
	LDA	#$B0
	STA	BAUDCONST,X
	LDA	#$0
	STA	BELL,X		; number of stop bits
	LDA	#FALSE
	STA	ISHIFT,X	; keyboard is not shifted
	STA	OSHIFT,X	; keyboard is not shifted
        LDA     #$20            ; slot << 4
        STA     NO,X

; main loop  
; set 80 column mode and clear screen
GETNEXTCHAR:
	LDY	NO,X		; 
GETNEXTCHARLOOP1:
        LDA     #$30            ; 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     $C080,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 loopkkkkkkkkkkkkkk

;
; serial start bit detected
;
SERIAL_START:
	JSR	GETSERIAL	; call serial input
	LDA	BYTE,X		; get byte read
	TAY

	LDA	ISHIFT,X
	BEQ	NOSHIFT
	LDA	BAUDETtoASCIIshifted,Y
	JMP	GNC_DISPLAY

NOSHIFT:
	LDA 	BAUDETtoASCII,Y

GNC_DISPLAY:
	CMP	#$FE
	BEQ	GNC_SHIFT
	CMP	#$FF
	BEQ	GNC_NOSHIFT
GNC_DISPLAY1:
	JSR	DISPLAYONSCREEN ; display it on the screen
	JMP	GETNEXTCHAR

GNC_SHIFT: 
	LDA	#TRUE 
	STA	ISHIFT,X
	JMP	GETNEXTCHAR
GNC_NOSHIFT:
	LDA	#FALSE
	STA	ISHIFT,X
	JMP	GETNEXTCHAR

;
; 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
;
; valid BAUDET Character?
;
	AND	#$7F		; clear MSB
	TAY
	LDA	ASCIItoBAUDET,y	; fetch baudet conversion
	BNE	OK2DISPLAY	; check MSB bit if set, then valid non shifted char
; user entered character not valid in Baudet, ring bell and return
	JSR	DOS_RING_BELL
	JMP	GETNEXTCHAR

OK2DISPLAY:
	PHA			; save baudet conversion byte for serial out
	LDA	BYTE,X		; restore character
        JSR     DISPLAYONSCREEN ; display it on the screen
;
; need to convert to BAUDET before sending to serial
;
	PLA			; restore character from stack
	STA	BYTE,X		; send converted character
	BMI	NOTSHIFTEDSEND	; check MSB bit if set, then non shifted char
; send shifted character
	LDA	OSHIFT,X	; is it already shifted?
	BNE	NSS2		; yes, then just send
	JSR	O_SHIFT		; send shift
	JMP	NSS2		; send character

; unshifted character
NOTSHIFTEDSEND:
	LDA	OSHIFT,X	; is it already shifted?
	BEQ	NSS2		; no, then just send
	JSR	O_UNSHIFT		; 
NSS2:
	JSR	PUTSERIAL	; call serial output 
	JMP	GETNEXTCHAR	; continue with poll loop
;
; unshift transmitter
O_UNSHIFT:
	LDA	#FALSE
	STA	OSHIFT,X
	LDA	BYTE,X
	PHA
	LDA	#UNSHIFT
	JMP	O_SHIFT_UNSHIFT
;
; shift transmitter
O_SHIFT:
	LDA	#TRUE
	STA	OSHIFT,X
	LDA	BYTE,X
	PHA
	LDA	#SHIFT
O_SHIFT_UNSHIFT:
	STA	BYTE,X
	JSR	PUTSERIAL	; call serial output 
	PLA
	STA	BYTE,X
	RTS


; 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 set bell ringing flag

	JSR	COUT1           ; call monitor output routine
	LDX	#SLOTADDRESS    ; restore X after montior call
	RTS
;
; Need to flag to return to bell routine
;
DOS_RING_BELL
        LDA     #50
        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 then line feeds to original line
	JSR	COUT1		;
	PLA
	STA	WINDOWTOP	; restore old top of display
	LDX	#SLOTADDRESS    ; restore X after montior call
	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/SHIFTED = random - used as shifted indicator
; 438,X/STOPBITS = 2
; 4B8,X/UNUSED where X = N (slot number) = 
; 5B8,X/BTYE

; serial input (45.45 baud,5 bits)
GETSERIAL:
	SEI
	LDA #5			; baudet code = start, 5 data bits, stop
	STA NCOUNT
	LDY NO,X
I_WAIT_START
;	LDA $C080,Y		; read input, waiting for start bit - waiting is done in main
;	BMI I_WAIT_START        ; loop to prevent hangs on spurious bit detection

	LDA BAUDCONST,X		; now delay 1.5 bit times, before getting first bit
	LDY #24			; was 9 for 110 baud, times 2.45 = 22
I_IWAIT:			;inner delay
	DEY
	BNE I_IWAIT
	SBC #$01
	BEQ I_GETBIT		; done delaying, branch to start getting data
	LDY #37      		; was 14 for 110 baud, time 2.45 = 34.3 (round up to 34)
	BNE I_IWAIT		; branch always

; get next bit
I_GETBIT:
	LDY NO,X
	LDA $C080,Y		; read input, waiting for start bitBNE I_IWAIT		; branch always

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

; delay 1 bit time before getting next bit
	LDA BAUDCONST,X		; fetch baud rate constant
	SEC
I_WAIT1:
	SBC #$01
	BEQ I_GETBIT
	LDY #24			; was 9 for 110 baud, x 2.45 = 22 for 45.45 baud
I_WAIT53:			; delay = 53X(BRATE-1) CYCLES
	DEY
	BNE I_WAIT53
	BEQ I_WAIT1
;
; recieved 5 bits, add leading zeros and wait for stop bit
;
I_MOD:
	LSR BYTE,X			; 1 zero shifted in
	LSR BYTE,X			; 2nd zero shifted in
	LSR BYTE,X			; 3rd zero shifted in

; wait for stop bit before returning
I_WAIT4STOP:
	LDA $C080,Y
	BPL I_WAIT4STOP
	RTS


;
; serial output  (45.45 baud, 5 bits, 2 stop)
;
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 #$06		; counting start bit - 6 bits
	STY NCOUNT		; save in COUNTER

	LDA #$00
	ASL BYTE,X		; 5B8 + X (CN) ???
O_NEXTBIT:
	ROR BYTE,X
	ROL			;  a bit
	ORA NO,X		; 
	TAY
O_STOP:
	SEC
	LDA $C081,Y		; output bit
	LDA BAUDCONST,X		; fetch baud rate delay
O_OUTER_DELAY:
	SBC #$1			; outer delay loop
	BEQ O_DELAY_DONE
	LDY #24		; 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,X
        TAY
        JMP O_STOP              ; send stop bits
O_DONE:
	TAY
	RTS

BAUDETtoASCII:
	DC.B	0
	DC.B	'E | $80
	DC.B	$0a | $80
	DC.B	'A  | $80
        DC.B    '  | $80
	DC.B	'S | $80
	DC.B	'I | $80
	DC.B	'U | $80
	DC.B	$0d | $80
	DC.B	'D | $80
	DC.B	'R | $80
	DC.B	'J | $80
	DC.B	'N | $80
	DC.B	'F | $80
	DC.B	'C | $80
	DC.B	'K | $80
	DC.B	'T | $80
	DC.B	'Z | $80
	DC.B	'L | $80
	DC.B	'W | $80
	DC.B	'H | $80
	DC.B	'Y | $80
	DC.B	'P | $80
	DC.B	'Q | $80
	DC.B	'O | $80
	DC.B	'B | $80
	DC.B	'G | $80
	DC.B	$fe
	DC.B	'M | $80
	DC.B	'X | $80
	DC.B	'V | $80
	DC.B	$ff
BAUDETtoASCIIshifted:
	DC.B	0
	DC.B	'3 | $80
	DC.B	$0a | $80
	DC.B	'- | $80
	DC.B	'  | $80
	DC.B	$07 | $80
	DC.B	'8 | $80
	DC.B	'7 | $80
	DC.B	$0d | $80
	DC.B	$05 | $80
	DC.B	'4 | $80
	DC.B	'' | $80
	DC.B	', | $80
	DC.B	'! | $80
	DC.B	': | $80
	DC.B	'( | $80
	DC.B	'5 | $80
	DC.B	'" | $80
	DC.B	') | $80
	DC.B	'2 | $80
	DC.B	$24 | $80
	DC.B	'6 | $80
	DC.B	'0 | $80
	DC.B	'1 | $80
	DC.B	'9 | $80
	DC.B	'? | $80
	DC.B	'& | $80
	DC.B	$fe
	DC.B	'. | $80
	DC.B	'/ | $80
	DC.B	'; | $80
	DC.B	$ff


ASCIItoBAUDET:
	DC.B	$0 |$C0	;NULL
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	$9 |$40	;ENQ
	DC.B	0
	DC.B	$B |$40	;BELL
	DC.B	0
	DC.B	0
	DC.B	$2 |$C0	;LF
	DC.B	0
	DC.B	0
	DC.B	$8 |$C0	;CR
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	$4  |$C0 ;space
	DC.B	$d  |$40 ;explaination point
	DC.B	$5  |$40 ;double quotes  translate to single quote
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	$1A |$40 ;ampersand
	DC.B	$5  |$40 ;single quote
	DC.B	$F  |$40 ;left parenthesis
	DC.B	$13 |$40 ;right parenthesis
	DC.B	0
	DC.B	$11 |$40 ;plus sign
	DC.B	$C  |$40 ;comma
	DC.B	$3  |$40 ;dash
	DC.B	$1C |$40 ;period
	DC.B	$1D |$40 ;slash
	DC.B	$16 |$40 ;0
	DC.B	$17 |$40 ;1
	DC.B	$13 |$40 ;2
	DC.B	$1  |$40 ;3
	DC.B	$A  |$40 ;4
	DC.B	$10 |$40 ;5
	DC.B	$15 |$40 ;6
	DC.B	$7  |$40 ;7
	DC.B	$6  |$40 ;8
	DC.B	$18 |$40 ;9
	DC.B	$E  |$40 ;colon
	DC.B	$1E |$40 ;semi - colon
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	$19 |$40 ;question mark
	DC.B	0        
	DC.B	$3  |$80 ;A
	DC.B	$19 |$80 ;B
	DC.B	$E  |$80 ;C
	DC.B	$9  |$80 ;D
	DC.B	$1  |$80 ;E
	DC.B	$D  |$80 ;F
	DC.B	$1A |$80 ;G
	DC.B	$14 |$80 ;H
	DC.B	$6  |$80 ;I
	DC.B	$B  |$80 ;J
	DC.B	$F  |$80 ;K
	DC.B	$12 |$80 ;L
	DC.B	$1C |$80 ;M
	DC.B	$C  |$80 ;N
	DC.B	$18 |$80 ;O
	DC.B	$16 |$80 ;P
	DC.B	$17 |$80 ;Q
	DC.B	$A  |$80 ;R
	DC.B	$5  |$80 ;S
	DC.B	$10 |$80 ;T
	DC.B	$7  |$80 ;U
	DC.B	$1F |$80 ;V
	DC.B	$13 |$80 ;W
	DC.B	$1D |$80 ;X
	DC.B	$15 |$80 ;Y
	DC.B	$11 |$80 ;Z
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	$5  |$40 ;single quote
	DC.B	$3  |$80 ;A (this section lower case)
	DC.B	$19 |$80 ;B
	DC.B	$E  |$80 ;C
	DC.B	$9  |$80 ;D
	DC.B	$1  |$80 ;E
	DC.B	$D  |$80 ;F
	DC.B	$1A |$80 ;G
	DC.B	$14 |$80 ;H
	DC.B	$6  |$80 ;I
	DC.B	$B  |$80 ;J
	DC.B	$F  |$80 ;K
	DC.B	$12 |$80 ;L
	DC.B	$1C |$80 ;M
	DC.B	$C  |$80 ;N
	DC.B	$18 |$80 ;O
	DC.B	$16 |$80 ;P
	DC.B	$17 |$80 ;Q
	DC.B	$A  |$80 ;R
	DC.B	$5  |$80 ;S
	DC.B	$10 |$80 ;T
	DC.B	$7  |$80 ;U
	DC.B	$1F |$80 ;V
	DC.B	$13 |$80 ;W
	DC.B	$1D |$80 ;X
	DC.B	$15 |$80 ;Y
	DC.B	$11 |$80 ;Z
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0
	DC.B	0

	
