M´kay, nachdem jetzt der Empfänger abgehandelt ist,
wollen wir uns mal der Generierung des Sendesingnales zuwenden.
Bei dem ersten Blick, fälllt bereits auf, dass es hier etwas wüster zugeht,
als im Empfänger.


Als Kern der eigentlichen Senderroutine wird hier der Comparematch mit dem OCR2 Register
zur Pulsweiten Variation genutzt. Dazu an gegebener Stelle mehr.

Der erste Teil in der Mainschleife soll den Befehl aufnehemen,
der gesendet werden soll. In diesem ersten Prog ist das nur einmal das Bitmuster
00010001 oder 00010010. Der eine Befehl schaltet eine Lampe ein, der andere aus.
Es ist auf jeden Fall ratsam, immer min. zwei BIT´s 1 zu setzen, um eine gewisse
Störsicherheit zu erreichen. Jedoch reicht auch das auf längere Zeit nicht. Ich werde
daher dazu übergehen, 16 BIT´s zu kodieren.


Nach diesem ersten Teil wird getestet, ob der neue Befehl auch tatsächlich neu ist und nicht
bereits gesendet wurde, wovon abhängt, ob dann überhaupt gesendet wird. Da muss man sich aber
überlegen, ob das nötig ist. Z.B. würden erhöhende und erniedrigende Befehle
auch mehrmals Sinn machen.

Nachdem das alles abgehandlet ist, wird der PIN, an dem der Sender hängt HIGH gesetz,
und eine Warteschleife aufgerufen, die bis TCNT2 = 250 dauert. An dieser Stelle ist
der Interrupt Enable für OCR2 noch inaktiv.
Nach dieser Funktion wird der zu sendende Befehl in einem zweiten Register zum späteren
vergleichen abgespeichert.

Darauf folgt die INIT Funktion, in welcher der Interrupt des Comparematches aktiv wird, der TNCT2
wird null gesetzt, an OCR2 der Wert 60 übergeben und der zu sendede Befehl in das shift Register shf
kopiert. Auf dieses wird später die LSL Operation angewendet.

Nun kommt endlich der interessante Teil, die eigentliche Senderoutine.
In diese ist eine Schleife progammiert, die elf mal durchlaufen wird.
In shfc wird festgehalten, wie oft die ISR aufgerufen wurde.

mehr1:
cpi shfc,11 (aus irgendeinem Grund
brlo mehr1 ist die doppelte abfrage
cpi shfc,11 nötig, sonst wird die Schleife
brlo mehr1 einen Zyklus zu früh verlassen -
ldi shfc,0 hat was mit einem der Statusbits zu tun)

Die Erklärung für die elf Mal
findet sich in der Erläuterung des Empfangprog´s.
Diese Schleife kann erst nach dem senden aller Datenbits verlassen werden. Vorher
wird sie mit der Verarbeitungsgeschwindigkeit wiederholt. Unterbrochen wird das nur
durch einen Comparematch mit OCR2, also beim ersten Mal bei TCNT2 = 60.
Daraufhin wird die ISR "hitvalue" aufgerufen.

Dort wird als erstes der logische Pegel, an dem der Sender sitzt, ivertiert. Das geht
Hand in Hand mit der Einstellung des Empfängers, der bei einem logischen Wechsel an INT1
interruptet.
Als zweites wird geprüft, ob die ISR im ersten Durchlauf ist, denn dann war der Interrupt zum
initialisieren des Empfängers.
Ist es jedoch mindestens der zweite Durchlauf, wird in Abhängigkeit des M(ost) S(inificant) B(it)
von shf die nächste Pulsdauer bestimmt und die besagte LSL Op auf shf gemacht.

ldi dauer,60
sbrs shf,7
ldi dauer,30
lsl shf

Als letztes wird shfc um eins erhöht.
Dann wird über reti wieder in die Schleife der Funktion senden1

cpi shfc,11
brlo mehr1
cpi shfc,11
brlo mehr1

zurückgesprungen.

Sind die elf Mal erreicht, wird der Interrupt durch OCR2 wieder deaktiviert und eine Warteschleife
auf Basis von TCNT0 bis 30 ausgeführt.
Danach wird der PIN wierder LOW gesetzt und nach MAIN zurückgekehrt.

Die Ganze Fummelei mit dem TIMSK könnte man im Prinzip auch mit sei; und cli machen, aber villeicht will man ja mal noch andere Interrupte nutzten, Tastermatrix z.B.

Code:
.include "m8def.inc"

.def shf = r17
.def shfc = r18
.def dauer = r19
.def zwischen = r20
.def tmp = r21
.def timermaskon = r22
.def timermaskoff = r23
.def befehl = r24
.def t = r25
.org 0x0000
	rjmp reset
.org OC2addr	; OCR2 Interrupt Vector Address
    rjmp hitvalue
reset:

	;Stack wird bei Interrupts benötigt!
	ldi r16,HIGH(RAMEND)
	out SPH,r16
	ldi r16,LOW(RAMEND)
	out SPL,r16
    ldi r16,0b01100000 ;internal Vref - Channel 0
	out ADMUX,r16
	ldi r16,0b10001110 ;singleconversion - prescaler 32 - int.enable 
	out ADCSRA,r16
	ldi r16,0b11111110
    out DDRC,r16
	;out PORTC,r16
    ldi r16,0b11110111
	out DDRD,r16
	ldi r16,0b00000011
	out TCCR0,r16
	ldi timermaskoff,0
    ldi tmp,0b00001100  ;interuppt on comparematch - presc 128
    out TCCR2,tmp
	;ldi r16,255
	;out OCR2,r16
	ldi timermaskon,0b10000000
    sei

mainloop:
wdr

sbic PIND,3
rjmp open
sbis PINB,5
ldi befehl,0b00010001
sbis PINB,4
ldi befehl,0b00010010
open:



cp zwischen,befehl
breq unten
ldi tmp,255
out PORTC,tmp
rcall pause
mov zwischen,befehl
rcall init
rcall senden1
ldi t,0
hoch:
sbic PIND,3
rjmp hoch
unten:
rjmp mainloop

pause:
ldi tmp,0
out TCNT0,tmp
warten:
     in tmp,TCNT0
     cpi tmp,250
     brlo warten
	 ldi tmp,0
	 out TCNT0,tmp

ret

init:
ldi tmp,0
     out TCNT2,tmp
	 ldi tmp,60
	 out OCR2,tmp
	 mov shf,befehl 
	 out TIMSK,timermaskon
ret

senden1:
mehr1:
cpi shfc,11
brlo mehr1
cpi shfc,11
brlo mehr1
ldi shfc,0
	 out TCNT0,shfc
     out TIMSK,timermaskoff
warten2:
     in tmp,TCNT0
     cpi tmp,30
     brlo warten2
	 ldi tmp,0
	 out TCNT0,tmp
ldi tmp,0
out PORTC,tmp
ret

hitvalue: 
   in tmp,PORTC
   com tmp
   out PORTC,tmp
   
   cpi shfc,1
   brlo senden 
   
   ldi dauer,60
   sbrs shf,7
   ldi dauer,30
   lsl shf
  
out PORTD,dauer
   out OCR2,dauer
   senden:
   inc shfc
reti
Kommentar:

Nch dem schreiben sind mir einoge Dinge aufgefallen, die noch nicht perfekt sind. Zum ersten kann ich sicher das erste INIT Bit schon als Datenbit nutzten und zum anderen in der senden1 Funktion die Warteschleife mit dem TCNT0 müsste auch wie zuvor über den Interrupt gehen.
Und wenn jemand weiß, woran das liegt, das ich die elfer Schleife zweimal brauche, bin ich dankbar für eine Erklärung.

Wenn ich dann mal die Zeit habe, mache ich mal eine Schaltungsskizze.

The Man