Source file: /~heha/basteln/Haus/Licht/Funklicht.zip/lve/lve.a12

; Licht-Verlängerung-Empfänger
;Hardware: PIC12F508 in Funkschaltsteckdose „EverFlourish EMW202R-1“
;			 ╔════╗╔════╗
;		5P	1╢ 5P ╚╝ 00 ╟8	00
;R1	Adressjumper	2╢ GP5	GP0 ╟7	Relais (H-aktiv)
;R3	Adressjumper	3╢ GP4	GP1 ╟6	Funkempfänger CMI2210L (H-aktiv)
;		frei	4╢ MCLR	GP2 ╟5	Kontrollausgang (LED, H-aktiv)
;			 ╚══════════╝
;Der eingebaute Controller erfüllt nicht die Randbedingung,
;als retriggerbares Monoflop agieren zu müssen: Neuprogrammierung.
;Der pinkompatible PIC12F629 bietet überall Pullups, nicht nur an GP0+1.
;Der pinkompatible PIC12F1501 bietet Low-Voltage-Programmierung.
;Der eingebaute Controller konnte nicht elektronisch identifiziert werden.
;Adressjumper	GP5/R1	GP4/R3	Mittleres Byte	Adresse aus GP5:4
;Steckdose 1	H	L/2kΩ	0x15		2
;Steckdose 2	L/2kΩ	H	0x45		1
;Steckdose 3	H	H	0x51		3
;(Nummer 4)	L	L	0x54		0
;220130	erstellt
;220225	erprobt (als Nummer 3)
;220313	erprobt (als Nummer 2), Bugfix Tabelle 1↔2
	radix	dec
	list	n=0,st=off
	nolist
	include	"p12f508.inc"
	list

	__idlocs (2022-1980)*512+2*32+16	; FAT-Datum: Jahr, Monat,Tag
	__config _IntRC_OSC	; Interner Oszillator 4 MHz = 1 MIPS
	cblock	0x10
bitct				; Bitzähler 0..24
bitsh:3				; 3 Bytes = 24 Bits
tic				; Timer0-Capture
ticr				; Timer0-Capture bei steigender Flanke
ontime:2			; 2 Bytes = 16 Bits Überlaufzähler Timer0: 2 Minuten
t0				; temporär
codeh				; Mittleres Byte des Ein- und Ausschaltkodes
	endc
code1	equ	0x154557	; Einschaltkode Steckdose 2
code0	equ	0x154554	; Ausschaltkode Steckdose 2
VTS	equ	4		; TMR0-Vorteiler (16) als Schiebewert
	
	org	0
	movwf	OSCCAL
;Adressjumper einlesen: Da GP4+5 kein Pullup haben,
;diese Ports kurz auf H programmieren und H (Ladung) bzw. L (Jumper) einlesen.
;Danach die auf H liegenden Eingänge als Ausgang und die mit L auf Eingang
;programmieren
	movlw	0x3A
	movwf	GPIO		; Relais aus
	movlw	0x0A
	tris	GPIO		; Ausgang aktivieren; GP5:4 kurz auf H
	movlw	0x3A
	tris	GPIO		; GP5:4 als Eingang
	nop
	movfw	GPIO		; GP5:4 einlesen
	movwf	t0
	andlw	0x30
	iorlw	0x3A		; 0 -> Eingang, 1 -> Ausgang
	tris	GPIO
	call	get_codeh
	movwf	codeh
;Mit Bitzeiten von 1,3 ms muss der Timer0 mit Vorteiler ≥8 betrieben werden.
;Hier 16 für Messzeiten bis 4 ms.
	movlw	0x80|(VTS-1)	; Timer0 Vorteiler 16, Pullup an GP1 aktivieren
	option

_vorn	bcf	GPIO,2
	clrf	bitct
_wrise	call	ckTO		; aktualisiert <tic>
	btfss	GPIO,1
	 goto	_wrise
;Die steigende Flanke muss, außer bei bitct==0, 1,3 ms nach der vorhergehenden Flanke kommen
	movfw	ticr
	subwf	tic,w
	movwf	t0		; t0 = vergangene Ticks, typ. 1200>>4
	addwf	ticr,f		; ticr = tic: Speichern
	movfw	bitct
	bz	_wfall
	movlw	1000>>VTS	; 1 ms = 0x3E
	subwf	t0,w		; w = Δt-1ms
	bnc	_vorn		; zu kurz
	movlw	1600>>VTS	; 1,6 ms = 0x64
	subwf	t0,w
	bc	_vorn		; zu lang
_wfall	call	ckTO		; aktualisiert <tic>
	btfsc	GPIO,1
	 goto	_wfall
; Die fallende Flanke entscheidet über die Bitwertigkeit
	movfw	ticr
	subwf	tic,w
	movwf	t0		; t0 = vergangene Ticks, typ. 300>>4 oder 900>>4 
	movlw	200>>VTS	; 0,2 ms = 0x0C
	subwf	t0,w
	bnc	_vorn		; zu kurz
	movlw	1500>>VTS	; 1,5 ms = 0x5D
	subwf	t0,w
	bc	_vorn		; zu lang
	movlw	650>>VTS	; 0,65 ms = 0x28
	subwf	t0,w		; C = Bit (richtige Polarität)
	movfw	bitct
	xorlw	24		; verändert C nicht!
	bz	_stopb
	incf	bitct,f		; Nicht über 24 hinaus inkrementieren
_sh0	rlf	bitsh,f
	rlf	bitsh+1,f
	rlf	bitsh+2,f	; Bit einschieben
	goto	_wrise		; nächstes Bit abwarten
_stopb
	bsf	GPIO,2		; Code /irgendeiner/ Fernbedienung empfangen
	bc	_sh0		; 1-Bit weiter einschieben
; Angekommenes Telegramm mit Ein- und Ausschaltkode vergleichen,
; die XOR-Befehle belassen allesamt C auf 0
	movfw	bitsh+2
	xorlw	upper(code1)
	bnz	_sh0		; Falscher Kode, 0-Bit einschieben
	movfw	bitsh+1
	xorwf	codeh,w		; Mittleres Byte, je nach Jumper
	bnz	_sh0		; Falscher Kode, 0-Bit einschieben
	movfw	bitsh
	xorlw	low(code1)
	bz	_ein		; Richtiger Einschalt-Kode
	xorlw	low(code1^code0)
	bnz	_sh0		; Falscher Kode, 0-Bit einschieben
	bcf	GPIO,0		; Richtiger Ausschalt-Kode: Relais aus
	goto	_vorn
_ein
	bsf	GPIO,0		; Relais einschalten
	movlw	high(120000000>>VTS)	; 0x70
	movwf	ontime
	movlw	upper(120000000>>VTS)	; 120 s = 2 Minuten = 0x72
	movwf	ontime+1	; Ausschalt-Timer starten
	goto	_vorn

ckTO	movfw	tic
	subwf	TMR0,w		; w = vergangene Ticks
	addwf	tic,f		; tic = TMR0 und C bei Überlauf
	skpc
	 retlw	0		; kein Timer0-Überlauf stattgefunden
	clrwdt			; Timer0: 4 ms, Watchdog: 16 ms
	btfss	GPIO,0		; Relais ein?
	 retlw	1		; keine Zeitmessung aktiv
	decf	ontime,f
	skpnz
	 decf	ontime+1,f
	skpnz
	 bcf	GPIO,0		; Relais per Timeout ausschalten
	retlw	2		; Zeitüberschreitung für Licht aufgetreten

get_codeh
	swapf	t0,w
	andlw	3
	addwf	PCL,f
	dt	0x54,0x45,0x15,0x51

	end
Detected encoding: UTF-80