Code:
;Programm
;CDurTonleiter rauf spielen
.include "m8def.inc"
.def tmp = r16 ;Mein Universallregister
.def tonwert = r17 ;aktueller Wert für den Ton
.def tonleiterEnde = r18 ;Hier wird gespeichert, ob die Tonleiter schon
;bis zu Ende gespielt wurde
.def lpm_reg = r0 ;Mein lpm-Register
.equ Summer = PB2 ;Summer an B.2
.equ time0 = 256-255 ;Timer0 für die Tonleiter
.equ time1 = 65536-1800 ;Damit wird der Timer1 vorgeladen, für die Sekunde
.equ daten_laenge = 7 ;Anzahl der Werte
.org 0x000
rjmp reset ;Interruptvektor "reset:"
.org OVF1addr
rjmp pruefSek ;Interruptvektor "pruefSek:"
.org OVF0addr
rjmp timerSummer ;Interruptvektor "timerSummer:"
reset:
;Stack einrichten
ldi tmp, HIGH(RAMEND) ;HIGH-Byte der obersten RAM-Adresse
out SPH, tmp
ldi tmp, LOW(RAMEND) ;Low-Byte der obersten RAM-Adresse
out SPL, tmp
;Timer Register für Ton werden belegt, hier Timer 0
ldi tmp, (1<<CS02) ;Prescaler ist 256
out TCCR0, tmp ;Register TCCR0 ist für den Prescaller zuständig
ldi tmp, time0 ;Hier wird der Timer vorgeladen
out TCNT0, tmp
;Timer Register für Sekunde werden belegt, hier Timer 1
ldi tmp, (1<<CS12) | (1<<CS10) ;Prescaler ist 1024
out TCCR1B, tmp
ldi tmp, HIGH(time1) ;Für den Timer1 (16Bit) benötigen
out TCNT1H, tmp ;wir 2 Register, in denen wir den Wert
ldi tmp, LOW(time1) ;für die 1 Sekunde (10000) speichern ->
out TCNT1L, tmp ;"TCNT1H" und TCNT2L"
ldi tmp, (1<<TOIE0) | (1<<TOIE1);Hier werden Interrupts nach Timer0 Überlauf eingeschaltet
out TIMSK, tmp ;Register TIMSK ist dafür zuständig
;Z-Register mit DB "tonleiter1" füllen
ldi ZH, HIGH(tonleiter1 * 2)
ldi ZL, LOW(tonleiter1 * 2)
sbi DDRB, Summer ;B.2 als Ausgang
sbi PORTB, Summer ;B.2 auf HIGH stellen
ldi tonleiterEnde, 0b00000000 ;tonleiterEnde auf 0 stellen
sei ;Interrupts zulassen
;Die Hauptschleife, die sich immer wiederholt und den Tonwert neu einliest
main:
lpm ;Daten von tonleiter1: holen
mov tonwert, lpm_reg ;erstes Byte in tmp verschieben - ersten Tonwert speichern
rjmp main ;immer wieder zurück zu main springen
;Läuft Timer1 über, so wird erstmal geprüft, ob der letzte Ton
;erreicht ist und der Timer1 wird neu vorgeladen
pruefSek:
push tmp ;tmp sichern
in tmp, SREG
push tmp ;SREG sichern
ldi tmp, HIGH(time1) ;Für den Timer1 (16Bit) benötigen
out TCNT1H, tmp ;wir 2 Register, in denen wir den Wert
ldi tmp, LOW(time1) ;für die 1 Sekunde speichern ->
out TCNT1L, tmp ;"TCNT1H" und TCNT2L"
lpm ;Daten von tonleiter1: holen
sbrc tonleiterEnde, 0 ;Ist tonleiterEnde = 0?
rjmp subtrahiereZ ;Wenn tonleiter = 1, dann subtrahiere Z um 1
addiereZ:
adiw ZL, 1 ;Z um 1 erhöhen
rjmp pruefSek2 ;zu "pruefSek2:" springen
subtrahiereZ:
sbiw ZL, 1 ;Z um 1 erniedrigen
pruefSek2:
ldi tmp, LOW ((tonleiter1 * 2) + daten_laenge) ;vergleiche LOW-Byte
cp ZL, tmp
ldi tmp, HIGH ((tonleiter1 * 2) + daten_laenge) ;vergleiche HIGH-Byte
cpc ZH, tmp
brne pruefTonrueckwaerts ;zu "pruefTonaus:" springen
sbr tonleiterEnde, 1 ;Hilfsvariable.1 auf 1 setzen
pruefTonrueckwaerts:
sbrc tonleiterEnde, 1 ;Ist tonleiter.1 = 0?
rjmp regwiederholen ;Wenn NEIN, dann zu "regiwederholen:"
;Wenn JA, dann prüfen, ob erster Ton
;wieder geladen wurde
prueftonaus:
ldi tmp, LOW (tonleiter1 * 2 - 1) ;vergleiche LOW-Byte
cp ZL, tmp
ldi tmp, HIGH (tonleiter1 * 2 - 1) ;vergleiche HIGH-Byte
cpc ZH, tmp
brne regwiederholen
ldi tmp, (0<<CS02) ;JA -> Timer0 abstellen
out TCCR0, tmp
regwiederholen:
pop tmp
out SREG, tmp ;SREG wiederholen
pop tmp ;tmp wiederholen
reti
;Läuft Timer0 über, so wird B.2 umgeschaltet, sodass Ton
;aus dem Summer zu hören ist
timerSummer:
push tmp ;tmp sichern
in tmp, SREG
push tmp ;SREG sichern
sbis PINB, Summer ;ist B.2 = 1?
rjmp timerSummer1 ;NEIN -> spring zu "timerSummer1:"
cbi PORTB, Summer ;JA -> setze B.2 auf 0
rjmp timerSummer2 ;springe zu "timerSummer2:"
timerSummer1:
sbi PORTB, Summer ;B.2 auf 1 setzen
timerSummer2:
out TCNT0, tonwert ;Timer0 neu vorladen
pop tmp ;SREG wiederholen
out SREG, tmp
pop tmp ;tmp wiederholen
reti
;Das sind die Werte, womit der Timer0 (Tonleiter-Timer) vorgeladen wird
;Anzahl der Wert muss GERADE sein
tonleiter1:
.db 256-55, 256-49, 256-44, 256-41, 256-37, 256-33, 256-29, 256-27
Musste allerdings bei der Prüfung, ob der erste Ton wieder erreicht ist eine 1 abziehen, sonst hät er einen Ton zu früh aufgehört.
Lesezeichen