;****** Kaeshofsteuerung 1.1 (c) Oliver Mezger 9.4.2009

.include "tn26def.inc"

;********* Hardware-Verbindungen

;*** PortA
.equ Lrot = 3
.equ Lgelb = 2  
.equ Lgruen = 1
.equ Lblau = 0
.equ Relais = 4
.equ VUdouble1 = 6 ;Verdoppeln der VU-Empfindlichkeit per Jumper
.equ VUdouble2 = 7
;*** PortB
.equ Sstart = 4
.equ Stuer = 5

;.equ selfTest = 3

;********* Software 

.def stat   = R3        ;Speichern des Status waehrend Interrupt
.def itempL = R4        ;Temoraere Register fuer Interrupts
.def temp = R16         ;Temp-Register zum Arbeiten
.def temp2 = R17
.def itemp  = R20       ;Temoraere Register fuer Interrupts
.def itemp2 = R21
.def sysTick = R22      ;Zaehlt die Timer1 Ueberlaeufe
.def sysTime = R23      ;Interne Zeit in Sekunden
.def state = R24        ;Prozesstatus

.set cpuClock = 1       ;Frequenz 1 MHz
.set timePrescale = 64
.set timeBase = timePrescale / cpuClock
.set sysTimeDiv = 500000 / 256 / timeBase ; damit SysTime im Halb-Sekundentakt


    rjmp init           ;Reset
    reti                ;INT0
    reti                ;I/O Pins
    reti                ;T1 Compare A
    reti                ;T1 Compare B
    rjmp T1_Over        ;T1 Overflow
    reti                ;T0 Overflow
    reti                ;USI Start
    reti                ;USI Overflow
    reti                ;EEPROM Ready
    reti                ;Analog Comparator
    rjmp ADC_Finish     ;ADC Conversation Complete

init:
    ldi temp,0b00011111 ;PortA als Ausgaenge    
    out DDRA,temp       
    ldi temp,0b11100000 ;PortA PullUps
    out PORTA,temp      
    ldi temp,0b00001111 ;PortB PullUps
    out PORTB,temp
    ldi temp,RAMEND     ;Oberste RAM-Adresse holen
    out SP, temp        ;Stack-Pointer initialisieren

    ldi temp,7
    out TCCR1B,temp     ;PreScaler /64
    ldi temp,0b00000100 ;Timer1 Overflow Interupt Flag
    out TIMSK,temp      ;Timer-Interrupt freigeben 
    ldi temp, 0b10101001;ADC Kanal9
    out ADMUX,temp
    ldi temp, 0b01101011;ADC laeuft frei
    out ADCSR, temp
    sei                 ;Interrupts global freigeben (I-Bit)
    sbis PINB,0         ;PB0 auf GND 
    rjmp vu_test        ;Test des ADC
    rjmp start
vu_test:
    sbi ADCSR,7         ;VU-Meter ein
    sbi ADCSR,6
vu_testloop:
    rjmp vu_testloop

T1_Over:
    in stat,SREG        ;Statusregister retten
    inc sysTick ;
    cpi sysTick,sysTimeDiv
    brmi t1over1
    clr sysTick
    inc sysTime         ;eine halbe Sekunde ist vergangen
t1over1:
    out SREG,stat       ;Statusregister herstellen
    reti

ADC_Finish:
    in stat,SREG        ;Statusregister retten
    in itemp,ADCL       ;lade ADC Ergebnis
    in itemp,ADCH
    sbic PINA,VUdouble1;doppelte Empfindlichkeit
    lsr itemp
    sbic PINA,VUdouble2;doppelte Empfindlichkeit
    lsr itemp
    cpi itemp,2
    brmi VU_Meter
    clr sysTime         ;Timer fuer auswarten zuruecksetzen
VU_Meter:
    sbrc itemp,3
    rjmp A_Red
    sbrc itemp,2
    rjmp A_Gelb
    sbrc itemp,1
    rjmp A_Green
A_Ausgabe:
    in itemp2,PORTA
    andi itemp2,$F0
    or itemp2,itemp 
    out PORTA,itemp2
    out SREG,stat       ;Statusregister herstellen
    reti
A_Red:
    ldi itemp,15
    rjmp A_Ausgabe
A_Gelb:
    ldi itemp,7
    rjmp A_Ausgabe
A_Green:
    ldi itemp,3
    rjmp A_Ausgabe

start:                  ;Einschaltverzoegerung wegen PIR-Melder
    sbi PORTA,Lblau     ;blaue LED leuchtet
    clr sysTime         ;Timer auf null
start2:
    sbic PINB,Sstart    ;wenn 1
    rjmp keinAnfang     ;dann kein Anfang
    rcall wait          ;wenn 0 warten
    sbic PINB,Sstart    ;wenn 1
    rjmp keinAnfang     ;dann kein Anfang
    rjmp anfang         ;sonst zu Anfang
keinAnfang: 
    cpi sysTime,2*30    ;Zeit bis Ruhezustand
    brmi start2         ;noch warten
ruheinit:
    in temp,PORTA
    andi temp,0b11100000;alle Ausgaenge 0
    out PORTA,temp
ruhe:
    sbrc sysTime,1      ;wenn Bit 1 gesetzt
    rjmp ma_setled      ;setze Leds
    cbi PORTA,Lblau     ;sonst loesche Leds
    rjmp ruhe2
ma_setled:
    sbi PORTA,Lblau     ;LED leuchtet
ruhe2:
    in temp,PINB
    com temp
    andi temp,0b00110000;Tuere oder Start
    breq ruhe
    rcall wait
    in temp,PINB
    com temp
    andi temp,0b00110000;Tuere oder Start
    breq ruhe
    sbrc temp,Sstart    ;wenn Starttaste gedrueckt
    rjmp anfang         ;direkt zum Anfang springen
    cbi PORTA,Lblau
    sbi PORTA,Lgruen
    clr sysTime         ;Timer auf null
beginwarten:
    sbic PINB,Stuer     ;wenn Tuere
    rjmp ruheinit
    cpi sysTime,2*10    ;Zeit bis Ausloesung
    brmi beginwarten    ;noch warten
anfang:
    cbi PORTA,Lblau
    cbi PORTA,Lgruen
    sbi PORTA,Lgelb
    sbi PORTA,Relais
    clr sysTime         ;Timer auf null
anfangwarten:
    cpi sysTime,2*60    ;Zeit bis warten auf Stille
    brmi anfangwarten   ;noch warten
;*** auf Stille warten
    clr sysTime         ;Timer auf null
    sbi ADCSR,7         ;VU-Meter ein
    sbi ADCSR,6
auswarten:
    cpi sysTime,2*6     ;Sekunden der Stille
    brmi auswarten
;*** ausschalten
    cbi ADCSR,7         ;VU-Meter aus
    sbi PORTA,Lrot
    cbi PORTA,Relais
    ;cbi PORTA,Lgelb
    clr sysTime
totwarten:
    cpi sysTime,2*30    ;Totzeit
    brmi totwarten
    rjmp ruheinit

wait:
    ldi temp,100        ;aeusseren Zaehler laden 100 ms
wl1:
    ldi temp2,250       ;inneren Zaehler 1ms bei 1Mhz
wl2:
    nop
    dec temp2           ;temp2--
    brne wl2            ;Sprung wenn nicht null
    dec temp            ;temp--
    brne wl1            ;Sprung wenn nicht null
    ret


