Source file: /~heha/basteln/Konsumgüter/Funkuhr/FunkFilt.zip/FunkFilt.a90

;Funkuhr-Filter für "spinnende" Funkuhren, hier:
;Modell: Funkwecker Lexor
;Serie: 5436/III/09/05
;Hersteller: NIKA USV GmbH, D-63667 Nidda
;filtert die Wetterdaten aus den Bits 0..15, kürzt diese Impulse auf 100 ms
;070512	Start, Inbetriebnahme, Einbau
;***************************************************************************
;Hardware:
;	PB0 (5) = Leitung zum Haupt-Controller (High-aktiv)
;	PB1 (6) = Standby-Steuerleitung (High = Standby) = INT0
;	PB2 (7) = Leitung vom Funkempfänger (High-aktiv)
;	PB3 (2) = Takt 32,768 kHz vom Uhrenquarz (XTAL1)
;	PB4 (3) = ungenutzt
;	PB5 (1) = Reset, ungenutzt
;Abgesehen von den Konfigurationsbits lief die Firmware auf Anhieb:-)
;Gemessene Ströme:
;Funkuhr selbst: 11 µA (Funkmodul Standby, keine Leuchtfolien-Beleuchtung)
;ATtiny: aktiv:	6,1 µA, Standby-Modus: 0,1 µA
.nolist
.include "tn12def.inc"
.list
.listmac

.def Sekunde = r18	;Sekundenzähler
.def LastB = r19	;letzter Zustand von PortB zur Pegelwechsel-Erkennung
.equ CPUCLK = 32768	;externer Uhrenquarz
.equ T0CLK = CPUCLK/256	;128 Hz (Timer0-Takt nach Vorteiler 256),
			;Überlauf (spätestens) aller 2 s
.cseg
;Für minimale Stromaufnahme läuft das gesamte Programm in ISRs
;********************************************************************
;* Interrupttabelle
;********************************************************************
.org 0		;Reset-Adresse
	rjmp	startup
.org INT0addr	;Interrupt wenn INT0 = Low
	rjmp	ISR_Wake
.org PCI0addr	;Pegelwechsel-Interrupt
	rjmp	ISR_Funk
.org OVF0Addr	;Interrupt bei Timer0-Überlauf
	rjmp	ISR_Ovl

.org INT_VECTORS_SIZE		;übrige Vektoren frei halten
	.dw	(__YEAR__+20)*512+__MONTH__*32+__DAY__	;FAT-Datum
	
;********************************************************************
;*  ISR Low-Pegel auf INT0 (Aufwecken vom Power-Down)
;********************************************************************
ISR_Wake:
;Retten von SREG und Registern nicht nötig! Hauptprogramm braucht nichts.
	ldi	r16,0b00100000
	out	MCUCR,r16	;Power-Down-Bit löschen
	out	GIMSK,r16	;INT0 fortan sperren
	in	LastB,PinB	;Tatsächlichen Pin-Zustand laden
	reti
;********************************************************************
;*  ISR Pegelwechsel (Funkuhr-Signal?)
;********************************************************************
ISR_Funk:
	in	r16,PinB	;Zustand einlesen
	eor	r16,LastB	;Änderungen?
	eor	LastB,r16	;jetzt: LastB = PinB, r16 = Änderungen
	sbrs	r16,2		;interessierende Leitung?
	 reti			;nein, nichts tun!
	sbrc	LastB,2
	 rjmp	IsHigh
	cbi	PortB,0		;Low-Pegel zum Hauptcontroller
	reti			;das war's
IsHigh:
	sbi	PortB,0		;High-Pegel zum Hauptcontroller
	inc	Sekunde		;Sekunde mitzählen (Sekunde 0 = 1)
	brne	Sek_OK
	dec	Sekunde		;auf 255 begrenzen
Sek_OK:	cpi	Sekunde,16
	brcs	PrepShort
		;hier: Timer0 programmieren zur Lückenerkennung
	ldi	r16,-T0CLK*1500/1000	;-192 = Überlauf nach 1,5 s
	out	TCNT0,r16
	reti
PrepShort:	;hier: Timer0 programmieren zur Impulsverkürzung
	ldi	r16,-T0CLK*100/1000	;-12 = Überlauf nach 100 ms
	out	TCNT0,r16	;Timer starten
	reti
;********************************************************************
;*  ISR Timer0-Überlauf (Minuten-Lücke erkennen ODER Impuls verkürzen)
;********************************************************************
ISR_Ovl:
	cpi	Sekunde,16
	brcs	MakeShort
	clr	Sekunde		;Sekundenzähler rücksetzen
	reti
MakeShort:	;Zweck des Timers: Pulsverkürzung
	cbi	PortB,0
	reti

;********************************************************************
;*  Mikrocontroller-Programmstart
;********************************************************************
startup:
	sbi	DDRB,0		;Datenport: Ausgabe für PB0=MOSI, zum Haupt-IC
	sbi	PortB,3		;Pull-Up für ungenutzte Anschlüsse
	sbi	PortB,4		;(hier unnötig)
	ldi	r16,0b00000100	;Timer0-Vorteiler 256, starten
	out	TCCR0,r16
	ldi	r16,0b00000010	;Timer0-Überlauf-Interrupt freigeben
	out	TIMSK,r16
	ldi	r16,0b10000000	;kein Analogvergleicher (Strom sparen)
	out	ACSR,r16
	sei
;********************************************************************
;*  Hauptschleife
;********************************************************************
PowerDown:
	ldi	r17,0b00110000
	out	MCUCR,r17	;Power-Down-Bit (für's nächste SLEEP) setzen
	ldi	r17,0b01000000
	out	GIMSK,r17	;INT0 freigeben (einzige Aufweckmöglichkeit)
MainLoop:
	sleep			;CPU (oder alles)
	sbic	PinB,1		;Standby-Leitung High? (nach Interrupt)
	 rjmp	PowerDown
	rjmp	MainLoop
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded