;**************************************************************************
;
; Filename : DISPLAY.ASM
; ----------------------
;
; (c) 1990/91 by Thomas Lehmann
;
;
; Jackophone V5.00
;
;
; Display Handling
;
;**************************************************************************


MODUL_START	set	*	; Größe des Moduls berechnen

; =========================================================================
;
; Type	: Unterprg.
;	: String im Display ausgeben, letztes Zeichen geshiftet oder \0
;
; Eingang	: Stringadresse  : ind_adr
;	: letztes Zeichen im String geshiftet oder NULL
;
; Ausgang	: String ab Cursorposition im Display ausgegeben
;
; Register	: ------
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

puts
	block
	pha		; Register retten
	phy
	ldy #$00	; Pointer auf aktuellen Character
loop	lda (ind_adr),y	; Character laden
	beq end		; String Ende

	pha		; Char. merken
	and #$7f	; Shift BIT ausblenden
	jsr putchar	; und ins Display
	iny		; Pointer auf nächstes Zeichen 
	pla		; Character zurück
	and #$80	; geshiftet ?
	beq loop	; nein, nicht der letzte Character

end	ply		; Register zurück
	pla
	rts
	bend


; =========================================================================
;
; Type	: Unterprg.
;	: Hex-Zahl ausgeben
;
; Eingang	: Wert im Accu
;
; Ausgang	: Hex-Wert 2-stellig im Display ausgeben
;
; Register	: ----
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

puthex	pha
	jsr puthex_0
	pla
	rts

puthex_0	pha		; Wert retten
	lsr		; oberes Nibble in unteres schieben
	lsr
	lsr
	lsr
	jsr puthex_1	; und ASCII ausgeben
	pla
	and #%00001111	; oberes Nibble ausblenden

puthex_1	clc
	cmp #$0a	; ist Wert <9
	bcc puthex_asc	; ja

	adc #6		; Hex A-F erzeugen
puthex_asc	adc #48		; ASCII dazu
	jmp putchar	; und ins Display


; =========================================================================
;
; Type	: Unterprg.
;	: Dezimal-Zahl ausgeben
;
; Eingang	: Wert im Accu
;
; Ausgang	: putdez   : dezimal-Wert 3-stellig im Display ausgeben
; 	: putdez99 : dezimal-Wert 2-stellig im Display ausgeben
; 	: putdez9  : dezimal-Wert 1-stellig im Display ausgeben
;
; Register	: Accu
;
; (c) by Thomas Lehmann Mai 1990
;
; =========================================================================

	; 16BIT, 5-stellig dezimal, ACCU = high, X = low
	; ----------------------------------------------
putdez16	stx dez_low	; Wert für Ausgaberoutine eintragen
	sta dez_high
	lda #00		; Anzahl der Stellen die nicht angezeigt werden
	bra dezout	; und dezimal ausgeben


	; 16BIT, 4-stellig dezimal, ACCU = high, X = low
	; ----------------------------------------------
putdez16_4	stx dez_low	; Wert für Ausgaberoutine eintragen
	sta dez_high
	lda #01		; Anzahl der Stellen die nicht angezeigt werden
	bra dezout	; und dezimal ausgeben


	; 3-stellig dezimal
	; -----------------
putdez	sta dez_low	; Wert für Ausgaberoutine eintragen
	lda #02		; Anzahl der Stellen die nicht angezeigt werden
	bra putdez_1	; und dezimal ausgeben


	; 2-stellig dezimal
	; -----------------
putdez99	sta dez_low	; Wert für Ausgaberoutine eintragen
	lda #03		; Anzahl der Stellen die nicht angezeigt werden
	bra putdez_1	; und dezimal ausgeben


	; 1-stellig dezimal
	; -----------------
putdez9	sta dez_low	; Wert für Ausgaberoutine eintragen
	lda #04		; Anzahl der Stellen die nicht angezeigt werden


putdez_1	stz dez_high
	bra dezout	; und dezimal ausgeben


; =========================================================================
;
; Type	: Unterprg.
;	: 16 BIT Zahl dezimal ausgeben
;
; Eingang	: Anzahl der Stellen die nicht angezeigt werden sollen im Accu
;	: low Byte des Wertes in "dez_low"
;	: high Byte des Wertes in "dez_high"
;
; Ausgang	: 16 BIT Wert dezimal im Display ausgeben, max. 5 stellig
;
; Register	: Accu
;
; (c) by Thomas Lehmann Mai 1990
;
; =========================================================================

dezout	phx		; Register retten
	phy
	sta hlp_reg	; Anzahl der Stellen merken
	ldy #7		; Offset auf Umrechnungstabelle laden
dezout_1	ldx #"0"	; ASCII Null laden
dezout_2	sec
	lda dez_low	; low Byte des Werts laden
	sbc dez_tab-1,y	; akt. Potenz aus Tabelle abziehen
	pha		; Resultat retten
	dey		; Offset auf nächsten Tabelleneintrag setzen
	lda dez_high	; high Byte des Werts laden
	sbc dez_tab+1,y	; akt. Potenz aus Tabelle abziehen
	bcc dezout_3	; Wert war kleiner

	sta dez_high	; Resultat ablegen
	pla		; low Resultat laden
	sta dez_low	; und als neuen Wert ablegen
	inx		; Ziffer erzeugen
	iny		; Offset richten
	bra dezout_2	; Wert noch nicht ermittelt

dezout_3	pla		; low Resultat laden
	dec hlp_reg	; soll Stelle ausgegeben werden ?
	bpl dezout_4	; nein, Stelle überspringen

	txa		; nach RA
	jsr putchar	; und ausgeben
dezout_4	dey		; nächste Stelle einstellen
	bpl dezout_1	; und berechnen

	lda dez_low	; Restwert laden, letzte Stelle
	ora #"0"	; ASCII erzeugen
	ply		; Register zurück
	plx
	jmp putchar	; letzte Stelle ausgeben und Ende

dez_tab	word 10
	word 100
	word 1000
	word 10000



; =========================================================================
;
; Funktion	: DM Betrag ausgeben, DM.Pf
;
; Eingang	: DM Betrag MSB Accu, LSB X
;	  Pfennige in Y
;
; Ausgang	: -------
;
; Register	: Accu
;
; (c) by Thomas Lehmann Oktober 1991
;
; =========================================================================

put_dm	jsr putdez16	; DM Betrag ausgeben
	lda #"."
	jsr putchar
	tya		; Pfennige laden
	jmp putdez99	; Pfennige 2-stellig ausgeben


; =========================================================================
;
; Funktion	: Wähltaste ausgeben
;
; Eingang	: Tastenwert im Accu
;
; Ausgang	: Wähltaste im Display ausgeben
;	: "*" und "#" gegen "/" und "H" ausgetauscht
;	: bei Erdtaste Punkt ausgegeben
;
; Register	: Accu
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

	ifndef EPROM2
wta_displ	cmp #ERD_ZIFF	; ist Ziffer Erdtaste ?
	beq wta_displ_1	; ja, direkt ausgeben

	jsr wta_to_asc	; Wtastenwert in ASCII wandeln
	cmp #"0"	; ist es 0-9 ?
	bcs wta_displ_3	; ja, Zeichen direkt ausgeben

	cmp #"*"	; ist es "*"
	beq wta_displ_2	; ja

	lda #"H"	; "#" gegen "H" austauschen, Hörton
	bra wta_displ_3	; und ausgeben

wta_displ_1	lda #"*"	; ASCII-Wert für Erdtaste laden
	bra wta_displ_3	; und ausgeben

wta_displ_2	lda #"/"	; "*" gegen "/" austauschen
wta_displ_3	jmp putchar	; und ins Display schreiben
	endif


; =========================================================================
;
; Type	: Unterprg.
;	: Wähltastenwert in ASCII wandeln
;
; Eingang	: Tastenwert im Accu
;
; Ausgang	: ASCII-Wert im Accu
;
; Register	: Accu
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

	ifndef EPROM2
wta_to_asc	jsr check_wta	; Wähltaste 1-9 ?
	cmp #11		; ist es "#"
	bcc wta_asc_1	; nein, Ziffer 0-9

	bne wta_asc_2	; es ist "*"

	lda #"#"	; ASCII-Wert laden
	bra wta_asc_3	; und Ende

wta_asc_2	lda #"*"	; ASCII-Wert laden
	bra wta_asc_3	; und Ende	

wta_asc_1	clc
	adc #48		; ASCII dazugeben
wta_asc_3	rts
	endif


; =========================================================================
;
; Type	: Unterprg.
;	: Zeichen im Display ausgeben
;
; Eingang	: auszugebener Character im Accu
;
; Ausgang	: Character im Displaybuffer abgelegt
;	: im Display an Cursorposition ausgegeben
;
; Register	: ------
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

putchar	phx		; Register retten
	phy

	ldx dp_bu_po	; akt. Pointer im Displaybuffer laden
	cpx #DP_BU_LA	; noch Platz frei
	bcc putchar_1	; ja, Zeichen anhängen

	; Character im Displaybuffer nach links rausschieben
	; --------------------------------------------------
	pha		; Character retten
	ldy #00		; 1. Character im Buffer einstellen
	tya		; Cursor auf 1. Position im Display setzen
	jsr curs_set	; Cursor setzen

dp_schieb	lda dp_buff+1,y	; 2.Character holen
	sta dp_buff,y	; und einen vorher ablegen
	jsr char_out	; Character ausgeben
	iny
	cpy #DP_BU_LA-1	; alle Character geschoben ?
	bcc dp_schieb	; nein, nächsten Character schieben
	pla		; auszugebenen Character zurückholen
	dex		; auf letze Position im Display stellen

putchar_1	sta dp_buff,x	; Char. im Displaybuffer ablegen
	jsr char_out	; und ins Display schreiben

	ply		; Register zurück
	plx
	rts


; =========================================================================
;
; Type	: Unterprg.
;	: einzelnes Zeichen ins Display schreiben
;
; Eingang	: auszugebenes Zeichen : Accu
;
; Ausgang	: Character im Display an Cursorposition ausgegeben
;
; Register	: -------
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

char_out	jsr dp_busy	; warten bis Display für Daten bereit
	pha		; Char. retten
	lda #RS_FLAG	; Display für ASCII-Character vorbereiten
	tsb Dp_rs	; BIT setzen
	pla		; Character zurück
	sta Display+1	; und ausgeben
	inc dp_bu_po	; Pointer auf akt. Char im Buffer +1
	rts


; =========================================================================
;
; Funktion	: "backspace" -> Zeichen vor Cursor löschen
; 	: "curs_left" -> Cursor 1x nach links
;
; Eingang	: -------
;
; Ausgang	: -------
;
; Register	: -------
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

curs_left	pha
	phx
	ldx #00		; Funktionscode: nur Cursor setzen
	bra cursor


backspace	pha
	phx
	ldx #01		; Funktion: Backspace ausführen

cursor	lda dp_bu_po	; Cursorposition laden
	dec a		; auf zu löschene Ziffer setzen
	jsr curs_set	; und Cursor setzen
	cpx #0		; Funktion Cursor setzen
	beq cursor_1	; ja, Ende

	jsr space	; Ziffer im Display clr
	jsr curs_set	; Cursor wieder auf akt. Eingabe setzen
cursor_1	plx
	pla
	rts


; =========================================================================
;
; Type	: Unterprg.
;	: einzelnes Zeichen ins Display schreiben, SPACE hinterher
;
; Eingang	: auszugebenes Zeichen im Accu
;
; Ausgang	: Character und SPACE im Display an Cursorposition ausgegeben
;
; Register	: ------
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

putchar_sp	jsr putchar	; Zeichen ausgeben
	bra space	; SPACE ausgeben


; =========================================================================
;
; Funktion	: SPACE ausgeben
;
; Eingang	: ------
;
; Ausgang	: SPACE im Display an Cursorposition ausgegeben
;
; Register	: ------
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

space	pha		; Accu retten
	lda #SPACE	; Characterwert für SPACE laden	
	jsr putchar	; und ausgeben
	pla
	rts

; =========================================================================
;
; Funktion	: Cursor setzen
;
; Eingang	: Cursorposition im Accu
;
; Ausgang	: --------
;
; Register	: --------
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

curs_set	pha		; Accu retten
	jsr dp_busy	; Display für Befehl vorbereiten
	sta dp_bu_po	; Pointer auf Character im Display setzen
	ora #$80	; Daten Speicher Adresse setzen
	sta Display	; und Cursor setzen
	pla		; Accu zurück
	rts

; =========================================================================
;
; Type	: Unterprg.
;	: Cursor einschalten
;
; Eingang	: ------
;
; Ausgang	: Cursor eingeschaltet, Zeichen unter Cursor blinkt
;
; Register	: -----
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

curs_on	bbs ST_CURS,feap_stat,curs_on_e	; Cursor ist eingeschaltet
	pha		; Accu retten
	jsr dp_busy	; Display für Befehl vorbereiten
	lda #$0f	; Befehl laden
	sta Display	; und ans Display weitergeben
	smb ST_CURS,feap_stat	; Cursor ist eingeschaltet eintragen
	pla		; Accu zurück                   
curs_on_e	rts


; =========================================================================
;
; Type	: Unterprg.
;	: Cursor ausschalten
;
; Eingang	: ------
;
; Ausgang	: Cursor ausgeschaltet
;
; Register	: -----
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

curs_off	bbr ST_CURS,feap_stat,curs_off_e	; Cursor ist ausgeschaltet

	pha		; Accu retten
	jsr dp_busy	; Display für Befehl vorbereiten
	lda #12		; Befehl laden
	sta Display	; und ans Display weitergeben
	rmb ST_CURS,feap_stat	; Cursor ist ausgeschaltet eintragen
	pla		; Accu zurück                   
curs_off_e	rts


; =========================================================================
;
; Type	: Hauptprg.
;	: Display löschen, Cursor aus
;
; Eingang	: ------
;
; Ausgang	: Display clr
;	: Cursor an 1. Position gesetzt und ausgeschaltet
;
; Register	: -----
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

dpclr_cuoff	jsr dp_clr	; Display clr
	bra curs_off	; Cursor ausschalten


; =========================================================================
;
; Type	: Hauptprg.
;	: Display löschen
;
; Eingang	: ------
;
; Ausgang	: Display und Displaybuffer mit SPACE beschrieben
;	: Cursor an 1. Position gesetzt
;
; Register	: -----
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

dp_clr	pha		; Register retten
	phx
	lda #$00	; 1. Cursorposition
	jsr curs_set	; Cursor setzen
	ldx #DP_BU_LA	; Displaybuffer Länge laden

	block
loop	lda #SPACE	; Space laden
	jsr putchar	; und ins Display schreiben
	dex		; alle Zeichen überschrieben ?
	bne loop	; nein, weiter
	bend

	txa		; 1. Cursorposition
	jsr curs_set	; Cursor setzen

	plx		; Register zurück
	pla
	rts


; =========================================================================
;
; Type	: Hauptprg.
;	: 40 uS warten bis Display für neue Zeichen bereit ist
;
; Eingang	: ------
;
; Ausgang	: Display im Befehlsmodus
;
; Register	: -----
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

dp_busy	pha		; Accu retten
	phx

	ldx #10		; Schleifenanzahl
dp_busy_1	dex		; 2 Cycles
	bne dp_busy_1	; 3 Cycles

	lda #RS_FLAG	; Display für Befehl vorbereiten
	trb Dp_rs	; BIT löschen
	plx
	pla		; Accu zurück
	rts


; =========================================================================
;
; Funktion	: Prg. für aktuelle Displayausgaben ausführen
; 	  wird von Haup-Schleife zyklisch aufgerufen
;
; Eingang	: ------
;
; Ausgang	: ------
;
; Register	: X
;
; (c) by Thomas Lehmann Oktober 1991
;
; =========================================================================

	ifndef EPROM2
displ_tab	word disp_reset	; wieder in Uhranzeige schalten
	word put_uhr	; Uhranzeige
	word put_vers	; Version anzeigen
	word whl_abl	; Wahlablauf-Cursor
	word st_dp_tim	; Display Timeout aus
	word _rts	; kein Displayprg. ausführen


displ_out	ldx struct_tim100+DISPL_TIM_O	; Display Timer abgelaufen ?
	beq displ_out_1	; ja, RESET

	ldx displ_prg	; Programmnr. laden	
displ_out_1	jmp (displ_tab,x)	; Programm ausführen



	; Display wieder in Uhranzeige schalten
	; =====================================
disp_reset	bbr MOD_BTA,modus,displ_res_1	; BTA war nicht aktiviert
	jsr bta_off	; LED-RAM clr, Key Ende ausführen

displ_res_1	jsr dp_clr	; Display löschen
	jsr key_ende	; Ende Taste ausführen

	rmb 7,sekunde	; Uhr direkt anzeigen
	ldx #UHR_DISPL	; Prg. Nr. für Uhranzeige
	lda whl_zcnt	; hat eine Wahl stattgefunden ?
	beq displ_res_2	; nein, Uhr einschalten

	jsr whl_displ	; Wahlziffern wieder ins Display
	ldx #WHLCU_DISPL	; Wahlablauf Cursor zeigen

displ_res_2	stx displ_prg	; und für Dsp. Prg. eintragen
	jmp (displ_tab,x)	; Programm ausführen
	endif


; =========================================================================
;
; Funktion	: Timer für Displayanzeige ohne Tastendruck aufziehen
;
; Eingang	: -------
;
; Ausgang	: -------
;
; Register	: -------
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

st_dp_tim	pha		; Register retten
	lda #DISPL_TIM	; Zeit bis Uhranzeige wieder ein laden
	sta struct_tim100+DISPL_TIM_O	; Display-Timer starten
	pla		; Register zurück
	rts



; =========================================================================
;
; Funktion	: Textlänge ermitteln, letztes Zeichen geschiftet
;
; Eingang	: Adr. des Textes in "ind_adr"
;
; Ausgang	: ind_adr zeigt auf Zeichen hinter dem Textende
;
; Register	: --------
;
; (c) by Thomas Lehmann Januar 1991
;
; =========================================================================

strlen	pha
strlen_lp	?inc16	ind_adr	; Ptr. auf 1. Textzeichen
	lda (ind_adr)	; Character laden
	beq strlen_end	; Endekennung gefunden

	and #$80	; geshiftet ?
	beq strlen_lp	; nein, nicht der letzte Character

	?inc16	ind_adr	; Ptr. auf nächstes Zeichen
strlen_end	pla
	rts


; =========================================================================
;
; Funktion	: Texte ausgeben
;
; Eingang	: low Adr. des 1. Textes in X-Reg
;	: high Adr. des 1. Textes in Y-Reg
;	: Anzahl Texte im ACCU
;
; Ausgang	: Text ausgegeben
;
; Register	: 
;
; (c) by Thomas Lehmann Januar 1991
;
; =========================================================================

init_dsptxt	sta anz_txt	; Anzahl verschiedener Texte merken
	stz akt_txt	; 1. Text einstellen
	stx dsp_txt	; Textadr. merken
	sty dsp_txt+1
	jmp puttxt	; und 1. Text ausgeben



nxt_dsptxt	inc akt_txt	; nächsten Text einstellen
	lda akt_txt
	cmp anz_txt	; bereits alle Texte ausgegeben ?
	bcc nxt_dsp_1	; nein, neuen Text ausgeben

	stz akt_txt	; wieder den 1. Text einstellen
	lda #$00


nxt_dsp_1	ldy dsp_txt	; low Byte des 1.Textes
	sty ind_adr	; für Textlänge
	ldy dsp_txt+1	; dito high
	sty ind_adr+1

	; Textadr. ermitteln
	; ------------------
nxt_dsp_lp	sec
	sbc #1		; aktuellen Text gefunden ?
	bmi nxt_dsp_out	; ja, Text ausgeben

	jsr strlen	; Textende ermitteln, (ind_adr)
	bra nxt_dsp_lp	; testen ob Textnr. gefunden ist
	
	; Text ausgeben
	; -------------
nxt_dsp_out ldx ind_adr	; Textadr. low
	ldy ind_adr+1	; dito high
	bra puttxt	; und Text ausgeben



; =========================================================================
;
; Funktion	: verschiedene Festtexte ausgeben
;	  put_aend
;	  put_dm_txt
;	  put_kzram
;	  put_rufnr
;	  put_babyruf
;
; Eingang	: -------
;
; Ausgang	: ---------
;
; Register	: X, Y
;
; (c) by Thomas Lehmann Oktober 1991
;
; =========================================================================


aend_txt	byte DSP_CLR
	shift "aendern ? (1=J, 2=N) : "

dm_txt	byte 0
	shift "DM:"

kzram_txt	byte	02|DSP_CLR|CURS_SET
	shift "! Zusatz-RAM fehlt !"

rufnr_txt	byte	DSP_CLR
	shift "Rufnummer ?"

baby_txt	byte 17|CURS_SET
	shift "Babyruf"




	; Text "aendern ?" ausgeben
	; -------------------------
put_aend	ldx #<aend_txt	; Text ausgeben
	ldy #>aend_txt
	bra puttxt


	; Text "DM:" ausgeben, Cursorpos. im Accu
	; ---------------------------------------
put_dm_txt	jsr curs_set	; Cursor setzen
	ldx #<dm_txt	; Text ausgeben
	ldy #>dm_txt
	bra puttxt


	; Text "Zusatz RAM fehlt" ausgeben
	; --------------------------------
put_kzram	ldx #<kzram_txt	; Text ausgeben
	ldy #>kzram_txt
	bra puttxt



	; Text "Rufnummer ?" ausgeben
	; ---------------------------
put_rufnr	ldx #<rufnr_txt	; Text ausgeben
	ldy #>rufnr_txt
	bra puttxt



	; Text "Babyruf" ausgeben
	; -----------------------
put_babyruf	ldx #<baby_txt	; Text ausgeben
	ldy #>baby_txt
;	bra ptxt_dspok


ptxt_dspok	lda displ_prg	; "puttxt" schaltet Display aus
	jsr puttxt
	sta displ_prg
	rts



; =========================================================================
;
; Funktion	: Texte ausgeben
;	  Display wenn angegeben clr
;	  Cursor gesetzt
;	  Text im Display ausgegeben
;
; Eingang	: Textadr. low X-Reg.
;	: Textadr. high Y-Reg.
;
; Ausgang	: ---------
;
; Register	: X, Y
;
; (c) by Thomas Lehmann Januar 1991
;
; =========================================================================

puttxt	pha		; Register retten

	stx ind_adr	; Textadr. ablegen
	sty ind_adr+1

	lda (ind_adr)	; Statusbyte laden
	bit #DSP_CLR	; Display clr ?
	beq puttxt_1	; nein

	jsr dp_clr	; Display löschen
puttxt_1	jsr curs_off	; Cursor ausschalten
	bit #CURS_ON	; Cursor einschalten ?
	beq puttxt_2	; nein, Cursor bleibt aus

	jsr curs_on	; Cursor einschalten
puttxt_2	bit #CURS_SET	; Cursor setzen ?
	beq puttxt_3	; nein

	and #%00011111 	; Cursorposition
	jsr curs_set	; Cursor setzen
puttxt_3	lda #NO_DISPL	; kein Display-Prg. ausführen
	sta displ_prg	; Prg.Nr. für Displayausgabe eintragen

	?inc16 ind_adr	; Adresse des Textes einstellen
	pla		; Register zurück
	jmp puts	; Text ins Display, Adr. in "ind_adr"



; --------------------------------------------------------------------------

HLP	set	*
_DISPLAY	equ	HLP-MODUL_START		; Größe des Moduls



