;**************************************************************************
;
; Filename : UHR.ASM
; ------------------
;
; (c) 1990 by Thomas Lehmann
;
;
; Jackophone V5.00
;
;
; Uhr mit automatischer Sommer/Winterzeit und Schaltjahrerkennung
;
;**************************************************************************


MODUL_START	set	*	; Größe des Moduls berechnen



; =========================================================================
;
; Funktion	: Notbetrieb der Uhr wenn Impuls der PIA nicht vorhanden
;	: rechte LED blinkt in "Uhr stellen" Taste
;
; Eingang	: zyklisch von Hauptprogrammschleife
;
; Ausgang	: Sekunden Impuls erzeugt wenn Notbetrieb eingeschaltet
;
; Register	: Accu
;
; (c) by Thomas Lehmann Mai 1990
;
; =========================================================================

uhr_notbetr	lda struct_tim+UHRNOT_TIM_O	; Timerwert laden
	bne uhr_not_end	; Sekunde nicht erreicht, Ende

	if GEBTEST
	?inc16 geb_cnt	; Gebührenimpuls simulieren
	smb GEB_IMP,hgeb_stat	; Impuls wurde erkannt
	endif

	lda #100	; 99=5 Min in 16Std falsch, Timer aufziehen
	sta struct_tim+UHRNOT_TIM_O

	ldy #LD_R|LD_OFF	; LED Wert laden
	lda #KEY_UHR	; Tastenwert der UHR stellen Taste laden
	bbs UHR_NOT,allg_stat,uhr_not_1	; Uhr Impuls wird erkannt

	inc sekunde	; Sekundenimpuls erzeugen
	ldy #LD_R|LD_T	; LED Wert laden

uhr_not_1	rmb UHR_NOT,allg_stat	; wird wenn Uhr läuft wieder gesetzt
	jmp set_prgled	; alle zum Tastenwert gehörenden LED`s aus

uhr_not_end	rts


; =========================================================================
;
; Funktion	: Uhr nachtriggern
;
;	: der Uhrbuffer hat folgenden Aufbau:
;	: -----------------------------------
;	: Wochentag, Jahr, Monat, Tag, Stunde, Minute, Sekunde
;
;
; Eingang	: zyklisch von Hauptprogrammschleife
;
; Ausgang	: Uhrzeit und Datum wenn Sekunde erreicht weiterschalten
;
; Register	: Accu, X, Y
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

WTAG	equ	0	; Position des Wochentags im Buffer
JAHR	equ	1	; dito, Jahr
MON	equ	2	; dito, Monat
TAG	equ	3	; dito, Tag
STD	equ	4	; dito, Stunde
MIN	equ	5	; dito, Minute
SEK	equ	6	; dito, Sekunde


uhr_trigger	lda sekunde	; Sekunde erreicht ?
	and #%00111111	; BIT`s für Uhrstatus ausblenden
	beq uhr_end	; nein, Uhr nicht nachtriggern

	bbs 6,sekunde,uhr_inc_01 ; Umschaltung bereits erfolgt
	jsr sw_umsch	; Sommer/Winterzeit Umschaltung testen

uhr_inc_01	rmb 7,sekunde	; Uhr neu ausgeben
	dec sekunde	; anstehende Sekunden-1
	ldx #UHR_BULA-1	; Offset auf Uhrbuffer laden, (Sekunde)
	inc uhr_buff,x	; Sekunde+1

uhr_inc	lda uhr_buff,x	; aktuellen Wert laden
	cmp uhr_tab_e,x	; Endwert erreicht ?
	bcs uhr_ueberl	; ja, Überlauf

	dex		; alle Werte getestet ?
	bpl uhr_inc	; nein

	jmp term_tst	; erreichte Termine prüfen und eintragen
uhr_end	rts


	; Endwert eines Uhrwertes erreicht
	; --------------------------------
	; Wochentag, Jahr, Monat, Tag, Stunde, Minute, Sekunde

	; Stunde erreicht ?
	; -----------------
uhr_ueberl	cpx #STD	; überlauf Stunde ?
	bne uhr_u_1	; nein, Tag testen
	inc uhr_buff+WTAG	; Wochentag nachführen

	; Tag erreicht ?
	; --------------
uhr_u_1	cpx #TAG	; Überlauf Tag ?
	bne uhr_u_2	; nein, Monat testen

	ldy uhr_buff+MON	; Monat laden
	dey		; Offset auf Tage/Monat Tabelle
	cmp tag_mon_tab,y	; Ist Tag im Monat erreicht ?
	bcc uhr_u_5	; nein, Tag so belassen


	; Februar, Schaltjahr und Jahrhundert testen
	; ------------------------------------------
	tay		; Tag merken
	lda uhr_buff+MON	; Monat laden
	cmp #02		; ist es Februar ?
	bne uhr_u_4	; nein, Startwert schalten

	lda uhr_buff+JAHR	; Jahr laden
	beq uhr_u_3	; es ist ein Jahrhundert

	and #$03	; ist es ein Schaltjahr ?
	bne uhr_u_4	; nein, Startwert schalten

uhr_u_3	cpy #30		; Februar hat 29 Tage im Schaltjahr
	bcs uhr_u_4	; Tag nicht mehr zugelassen, Startwert schalten


	; Tag so belassen
	; ---------------
uhr_u_5	dex		; nächsten Eintrag einstellen
	bra uhr_inc	; nächsten Eintrag testen


	; Monat erreicht ?
	; ----------------
uhr_u_2	cpx #MON	; Überlauf Monat ?
	bne uhr_u_4	; nein

	rmb 6,sekunde	; Sommer/Winterzeit wieder testen


	; Startwert einstellen
	; --------------------
uhr_u_4	lda uhr_tab_a,x	; Startwert laden
	sta uhr_buff,x	; und neu starten
	dex		; nächsten Wert einstellen
	beq uhr_end	; alle Werte getestet, Ende

	inc uhr_buff,x	; nächsten Eintrag nachführen
	bra uhr_inc	; nächsten Eintrag testen


	; ==================
	; Startwerte der Uhr
	; ==================

uhr_tab_a	byte 0		; Start-Wochentag
	byte 0		; Start-Jahr
	byte 1		; Start-Monat
	byte 1		; Start-Tag
	byte 0		; Start-Stunde
	byte 0		; Start-Minute
	byte 0		; Start-Sekunde


	; ================
	; Endwerte der Uhr
	; ================

uhr_tab_e	byte 7		; End-Wochentag
	byte 100	; End-Jahr
	byte 13		; End-Monat
	byte 29		; End-Tag
	byte 24		; End-Stunde
	byte 60		; End-Minute
	byte 60		; End-Sekunde


	; =====================
	; Anzahl der Tage/Monat
	; =====================

tag_mon_tab	byte 32		; Januar
	byte 29		; Februar 28 Tage, Schaltjahr = 29 Tage
	byte 32		; März
	byte 31		; April
	byte 32		; Mai
	byte 31		; Juni
	byte 32		; Juli
	byte 32		; August
	byte 31		; September
	byte 32		; Oktober
	byte 31		; November
	byte 32		; Dezember



; =========================================================================
;
; Funktion	: Sommer/Winterzeit Umschaltung testen (02:00:00)
;	  letzter Sonntag im März 1 Stunde vor
;	  letzter Sonntag im September 1 Stunde zurück
;
; Eingang	: jede Sekunde
;
; Ausgang	: Sommer bzw. Winterzeit eingestellt wenn erforderlich
;
; Register	: Accu, X, Y
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

sw_umsch
	block
	bbr DIP_SUMTIME,dip_stat,end	; keine auto Sommerzeit

	lda uhr_buff+WTAG	; Wochentag laden, ist es Sonntag ?
	bne end		; nein

	ldx uhr_buff+MON	; Monat laden
	dex		; Offset auf Tage/Monat Tabelle
	lda tag_mon_tab,x	; letzten Tag im Monat laden
	sec
	sbc #8		; Woche abziehen
	cmp uhr_buff+TAG	; ist es der letzte Sonntag im Monat ?
	bcs end		; nein

	ldx #02		; Offset auf Sommer/Winter Tabelle
	ldy #UHR_BULA-1	; Offset auf Uhrbuffer laden, (Sekunde)

loop	lda sw_tab,x	; Zeit der Umschaltung
	cmp uhr_buff,y	; ist Zeit erreicht ?
	bne end		; nein
	dey		; nächsten Wert einstellen
	dex
	bpl loop	; nächsten Wert testen

	lda uhr_buff+MON	; aktuellen Monat laden
	cmp #03		; ist es März ?
	bne winter	; nein, Winterumschaltung testen

	inc uhr_buff+STD	; Stunde +1, Sommerzeit
	bra sw_1

winter	cmp #09		; ist es September ?
	bne end		; nein, keine Umschaltung

	dec uhr_buff+STD	; Stunde -1, Winterzeit
sw_1	smb 6,sekunde	; Sommer/Winter erst bei nächsten Monat testen
end	rts

sw_tab	byte 01,59,59	; Zeit der Umschaltung, Std., Min, Sek.
	bend

; =========================================================================
;
; Funktion	: Uhr im Display anzeigen
;
; Eingang	: -------
;
; Ausgang	: Uhrzeit, Datum und Schlüsselschalter im Display angezeigt
;
; Register	: Accu, X, Y
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

put_uhr	bbs 7,sekunde,p_u_end	; Uhrzeit wurde bereits ausgegeben

	; erreichten Termin ausgeben ?
	; ----------------------------
	lda err_term	; ist ein Termin erreicht ?
	beq put_uhr_1	; nein, Uhr ausgeben

	jsr put_errterm	; erreichten Termin ausgeben
	bcs p_u_end	; Text wird ausgegeben

put_uhr_1	smb 7,sekunde	; akt. Uhrzeit ist ausgegeben
	jsr dpclr_cuoff	; Display löschen, Cursor aus
	jsr st_dp_tim	; Display Timer aufziehen

	; Uhr ausgeben
	; ------------
	lda uhr_buff+WTAG	; Wochentag laden
	asl		; Offset auf Tabelle erzeugen
	tax
	lda wtg_tab,x	; 1.Zeichen laden
	jsr putchar	; und ausgeben
	lda wtg_tab+1,x	; 2.Zeichen laden
	jsr putchar_sp	; ausgeben, SPACE hinterher

	ldy #UHR_BULA-2	; Offset auf Uhrbuffer laden

	block
loop	lda format_tab,y	; Uhr im richtigem Format ausgeben
	tax		; aktuelles Zeichen laden
	lda uhr_buff,x	; Uhr-Wert laden
	jsr putdez99	; und dezimal ausgeben, max. 99
	lda trnz_tab,y	; Trennzeichen laden
	jsr putchar	; und ausgeben
	dey		; alle Zeichen ausgegeben ?
	bpl loop	; nein
	bend

	jmp put_ss	; Zustand des SS ausgeben

p_u_end	rts


wtg_tab	text "SoMoDiMiDoFrSa"	; Wochentage


	; Aufbau der Uhranzeige
	; ---------------------
	; Wochentag, Tag, Monat, Jahr, Stunde, Minute, Sekunde
	; "Fr 13.02.90 23:24:49"

	; der Uhrbuffer hat folgenden Aufbau:
	; -----------------------------------
	; Wochentag, Jahr, Monat, Tag, Stunde, Minute, Sekunde

format_tab	byte SEK,MIN,STD,JAHR,MON,TAG ; Ausg. Format der Uhr, rückwerts !

trnz_tab	text " :: .."	; Trennzeichen


; =========================================================================
;
; Funktion	: Uhrzeit einstellen
;
; Eingang	: Offset auf Tastaturtabelle in X-Reg.
;	: Tastenwert im Accu
;
; Ausgang	: -----------
;
; Register	: X
;
; (c) by Thomas Lehmann Feb. 1990
;
; =========================================================================

uhrset_txt	byte  DSP_CLR|CURS_ON
	shift "Uhrzeit (HHMMSS): "

	byte  DSP_CLR|CURS_ON
	shift "Datum(TTMMJJWW):"


key_uhr	stz input_po	; keine Zeichen im Input-Buffer

	ldx wta_prg	; Wähltastenprg. laden
	cpx #WTA_UHRSET	; ist Uhr stellen bereits aktiv ?
	bne key_uhr_1	; nein, aktivieren (1.Tastendruck)

	ldx uhr_timdat	; Offset auf Uhrbuffer laden
	beq key_uhr_1	; letzte Anzeige war Datum

	; Eingabe Datum vorbereiten
	; -------------------------
	stz uhr_timdat	; Datum stellen eintragen
	ldx #8		; Anzahl der Eingaben
	stx anz_input	; und setzen
	jmp nxt_dsptxt	; nächsten Uhr Text ausgeben


key_uhr_1	jsr key_ende	; Ende-Taste ausführen
	ldy #LD_L|LD_ON	; LED-Wert laden
	jsr set_prgled	; und LED einschalten

	ldx #WTA_UHRSET	; Prg. Nr. bei Wähltaste
	stx wta_prg	; einschalten

	; Zeiteingabe vorbereiten
	; -----------------------
	ldx #6		; Anzahl der Eingaben
	stx anz_input	; setzen
	ldx #UHR_BULA-1	; Offset auf Sekunde laden
	stx uhr_timdat	; und eintragen

	ldx #<uhrset_txt	; Textadr. laden
	ldy #>uhrset_txt
	lda #ANZ_UHRTXT	; Anzahl der Texte laden
	jmp init_dsptxt	; Textwahl initialisieren



	; =======================
	; Einsprung bei Wähltaste
	; =======================
wta_uhrst	ldx input_po	; Offset auf akt. Eingabe
	cpx anz_input	; läuft "aendern ja/nein" Abfrage ?
	bcs wta_uhrst_2	; ja

	jsr check_wta	; Taste im Gültigkeitsbereich ?
	bcs wta_uhr_end	; nein, Ende

	jsr input	; Tastenwert eintragen
	inx		; Offset auf akt. Eingabe
	cpx anz_input	; Uhrwert komplett eingegeben ?
	bcc wta_uhr_end	; nein, noch nicht ändern abfragen

	jmp put_aend	; ändern J/N Text ausgeben

wta_uhr_end	rts


	; eingegebenen Uhrwert eintragen
	; Wochentag, Jahr, Monat, Tag, Stunde, Minute, Sekunde
	; ----------------------------------------------------

wta_uhrst_2	cmp #2		; ändern (Wtaste "2") ?
	beq wta_uhrst_3	; nicht ändern
	bcs wta_uhr_end	; ungültige Taste

	rmb 6,sekunde	; Zeit geändert, Sommer/Winter wieder testen
	ldy uhr_timdat	; Offset auf Uhreintrag laden
	lda input_po	; Pointer auf nächstes Zeichen im Buffer
	lsr		; 2 Byte Einträge
	tax
	dex		; auf letzte Eingabe stellen

get_uhrval	jsr get_input	; Wert aus Inputbuffer holen
	sta uhr_buff,y	; Uhrwert speichern
	lda uhr_timdat	; wird Zeit eingetragen ?
	bne get_uval_1	; ja

	iny		; Datum wird von 0-TAG eingetragen
	iny

get_uval_1	dey		
	dex		; alle Eingaben eingetragen ?
	bpl get_uhrval	; nein, nächsten Uhrwert eintragen

wta_uhrst_3	lda uhr_timdat	; Offset auf Uhrbuffer laden
	bne key_uhr	; Zeit wurde eingestellt, Datum vorbereiten

uhrst_off	jmp key_ende	; Ende-Taste ausführen




	; =========================
	; Einsprung bei Lösch Taste
	; =========================
uhrset_clr	lda input_po	; Offset auf akt. Eingabe
	beq wta_uhr_end	; kein Zeichen eingegeben, Ende

	dec input_po	; Anzahl Eingaben -1
	jmp backspace	; letztes Zeichen im Display löschen




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

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

