; *** Servotester V 0.5 (c) Oliver Mezger 23.2.2010
; CC-Lizenz: creativecommons.org/licenses/by-sa/3.0/de/
; Assemblercode ist nicht vollständig und nur beispielhaft
.include "m8def.inc"

;*** Zuordnungen zu den Ports ***

.equ SegmenteIn = PIND
.equ SegmenteOut = PORTD
.equ SegmenteDdr = DDRD
.equ SteuerungIn = PINB
.equ SteuerungOut = PORTB
.equ SteuerungDdr = DDRB
.equ StelleIn = PINC
.equ StelleOut = PORTC
.equ StelleDdr = DDRC

.def null = R23     ;Register mit 0
.def tmp = R16      ;tmp-Register zum Arbeiten
.def tmp2 = R17     ;als lokale, temporaere Variablen
.def stelle = R18   ;Stelle die dargestellt wird (neg. Logik 110,101,011)
.def itmp = R21     ;tmp-Register fuer Interrupt Service Routine (ISR)

;*** Interrupttabelle bei Mega8 sind die Adressen im Wort-Abstand daher rjmp

    rjmp reset      ;Einsprung nach Reset
    .org OVF0addr   ;Einsprung nach Timer 0 Ueberlauf
    rjmp isrAnzeige ;fuer Anzeigen ISR
    .org ADCCaddr   ;Einsprung AD-Wandler
    rjmp isrAdc     ;fuer ADC ISR
    .org $2a        ;Ende der Interruptvektoren nun Code

isrAnzeige: ;ISR wird mit Systemtakt/8/256 mal aufgerufen (488 Hz)
    in itmp,SREG            ;SREG retten
    push itmp
    cpi stelle,0b111        ;wenn nicht Stelle 4
    brne nstelle            ;dann naechste Stelle
    ldi stelle,0b110        ;Stelle1 initialisieren
    ldi XH, high(anzeige)   ;Datenzeiger initialisieren
    ldi XL, low(anzeige)
nstelle:
    ld itmp,x+
    ldi ZH, high(bcd_7*2)   ;Datenzeiger initialisieren
    ldi ZL, low(bcd_7*2)
    add ZL,itmp             ;Addiere Position
    adc ZH,null
    lpm itmp, z             ;lade Daten aus Flash
    cpi stelle,0b101        ;wenn nicht stelle 1
    brne keindp             ;dann kein Dezimalpunkt
    andi itmp,0b01111111    ;sonst setze Dezimalpunkt
keindp:
    out SegmenteOut,itmp    ;ausgeben Spalte
    in itmp, StelleOut      ;lade StellenPort
    andi itmp,0b11111000    ;maskiere Stellenbits
    or itmp,stelle          ;fuege Stellenmuster hinzu
    out StelleOut,itmp      ;Stelle einschalten
    lsl stelle              ;naechste Stelle kein rol verwenden!
    inc stelle
    andi stelle,0b111       ;die rausgeschobene 1 wegmaskieren
    pop itmp                ;SREG wiederherstellen
    out SREG,itmp
    reti                    ;return from Interrupt 

isrAdc: ;ISR fuer AnalogDigital-Wandler
    reti

reset: ; Initialisierung und Hauptprogramm
    ldi tmp, high(RAMEND)   ;Stackpointer initialisieren
    out SPH, tmp
    ldi tmp, low(RAMEND)
    out SPL, tmp
    ldi tmp,2               ;Timer 0 mit Systemtakt/8 betreiben
    out TCCR0,tmp
    in tmp,TIMSK            ;Timerinterrupt einschalten
    ori tmp, 1 << TOIE0
    out TIMSK,tmp
    ldi null,0
    ldi XH, high(anzeige)   ;Datenzeiger initialisieren
    ldi XL, low(anzeige)
    st X+,null              ;Feld mit 0 initialisieren
    st X+,null
    st X+,null
    ldi tmp,0xff
    out SegmenteDdr,tmp
    ldi tmp,7
    out StelleDdr,tmp
    ldi stelle,6
    sei                     ;globale Interruptfreigabe
loop: 
    rjmp loop

bcd_7:
    .db 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90

    .dseg; Datenbereich
anzeige:
    .byte 3; Feld mit 3 Byte 
