/* * TGI_10.asm * * Created: 28.11.2013 13:37:11 * Author: Ehlers/Meyer/Boekhoff/Jaehn */ .include "m16def.inc" .def TMP = R16 ; Definieren Sie für die Gatter R20 bis R23 die Namen GATTER_TYPE, COUNTER, CURRENT_GATTER, BLINK. .def GATTER_TYPE = R20 .def COUNTER = R21 .def CURRENT_GATTER = R22 .def BLINK = R23 ; Definieren Sie die Konstanten NUM_GATTER_TYPES = 3, TYPE_AND = 0, TYPE_NAND = 1, TYPE_OR = 2 und TYPE_UNKNOWN = 3. .equ NUM_GATTER_TYPES = 3 .equ TYPE_AND = 0 .equ TYPE_NAND = 1 .equ TYPE_OR = 2 .equ TYPE_UNKNOWN = 3 .dseg .org $0100 ; Stellen Sie im RAM unter dem Label GATTER_TYPES 4 Byte zur Verfügung. GATTER_TYPES: .byte 4 .cseg ; Interrupt Vektor Tabelle .org $0000 rjmp init .org $0026 ; OC0addr rjmp TIMER0_COMP_ISR ; Legen Sie jeweils die vier Ausgaben der Gatter unter den Labeln AND_GATTER, NAND_GATTER und OR_GATTER im ROM ab. ; Verwenden Sie für jede Ausgabe jeweils 1 Byte. ; Diese sollen direkt zu der sequentiellen Belegungen der Eingänge mit den Werten null bis drei korrespondieren. .org $002A AND_GATTER: .db 0b00000000, 0b00001001, 0b00010010, 0b00111111 NAND_GATTER: .db 0b00100100, 0b00101101, 0b00110110, 0b00011011 OR_GATTER: .db 0b00000000, 0b00101101, 0b00110110, 0b00111111 .org $0060 ; ***************************************************************************** ; Initialisierung ; ***************************************************************************** init: ; Initialisierung des Stack Pointers ldi TMP, high(RAMEND) out SPH, TMP ldi TMP, low(RAMEND) out SPL, TMP ; Portdefinitionen (PORT A und B) ldi TMP, 0b11011011 out DDRA, TMP out DDRB, TMP ; Portdefinitionen (PORT C) out DDRC, TMP ; Portdefinitionen (PORT D) ldi TMP, 0b11111110 out DDRD, TMP ; Initialisierung der Anfangswerte einzelner Register ldi BLINK, 0 ; ------ TODO ------ ; ; Initilaisierung des Timers ; Vergleichswert für Timer0 (~100 ms) in das Compare Register schreiben ; ------ TODO ------ ; ldi TMP, 100 out OCR0, TMP ; Clear-Timer-On-Compare-Match (CTC) Modus einstellen & ; Prescaler auf clk/1024 für den Timer0 einstellen ldi TMP, (1<<COM01) | (1<<COM00) | (1<<WGM01) | (1<<CS02) | (1<<CS00) out TCCR0, TMP ; Interrupt für Compare-Match des Timers0 lokal aktivieren ldi TMP, (1<<OCIE0) out TIMSK, TMP ; Interrupts global aktivieren sei rjmp main ; Das Hauptprogramm verbleibt in einer Endlosschleife, bis an PD0 ein High-Pegel detektiert wird. ; Wärend des Wartens sollen die LEDs ausgeschaltet sein und keine Spannung an den Eingängen des Gatters anliegen. ; Ist der Taster gedrückt, so beginnt das Hauptprogramm sequentiell die einzelnen Gatter des ICs mithilfe des Unterprogramms TEST_GATTER zu übeprüfen ; und speichert die einzelnen Gattertypen entsprechend im RAM unter dem Label GATTER_TYPES ab. ; Wurden alle Gatter des ICs übeprüft, erfolgt die Ausgabe mithilfe des Unterprogramms OUTPUT. ; Dieses erwartet im Register R16 den Typ des ICs, welcher dem ersten im RAM gespeicherten Typen entspricht, der ungleich TYPE_UNKNOWN ist. ; Sollte es sich um ein unbekanntes oder komplett defektes Gatter handeln, so enthält R16 den Typ TYPE_UNKNOWN. ; Anschließen wird wieder zu main gesprungen. main: sbis PIND, PIND0 rjmp main ; Analyse starten ldi CURRENT_GATTER, 0 ; aktuelles zu pruefendes Gatter ldi XH, high(GATTER_TYPES) ldi XL, low(GATTER_TYPES) gatter_loop: inc CURRENT_GATTER ; naechstes Gatter call TEST_GATTER st X+, GATTER_TYPE ; ermittelten Gatter-Typ speichern cpi CURRENT_GATTER, 4 ; sind alle Gatter ueberprueft? brne gatter_loop ldi COUNTER, 4 ld R16, -X ; lade den ersten Typen ldi XH, high(GATTER_TYPES) ldi XL, low(GATTER_TYPES) suche_typ: ld R16, X+ ; speichere den Typ cpi R16, TYPE_UNKNOWN ; ist der Typ nicht unbekannt? brne typ_gefunden dec COUNTER brne suche_typ typ_gefunden: call OUTPUT ; Ausgeben des Vergleichsergebnisses: R16 enthaelt den Typ des gesamten Bausteins rjmp main ; Dieses Unterprogramm testet das in CURRENT_GATTER gegebene Gatter des ICs und ; liefert als Ergebnis in GATTER_TYPE den Gattertypen zurück. ; Dazu werden die Eingänge des Gatters sequentiell mit den Eingaben null bis drei belegt und die Ausgabe ensprechend der im ROM abgelegten Prüfwerte verglichen. ; Es muss bei der Ansteuerung der einzelnen Gatter darauf geachtet werden, dass die Ausgabe der LEDs nicht beeinflusst wird. ; Zwischen dem Setzen der Eingaben der Gatter und dem Auslesen der Ausgänge sollte eine kleine Wartezeit von einem Leertakt eingehalten werden. TEST_GATTER: ldi ZH, high(AND_GATTER<<1) ldi ZL, low(AND_GATTER<<1) ldi GATTER_TYPE, TYPE_AND ; Nummber des zu ueberpruefenden Gatter-Typen ldi COUNTER, 4 ; wie viele Tests wurden pro Gatter-Art schon ausgefuehrt type_loop: lpm TMP, Z+ ; nachsten Test laden out PORTA, TMP ; auf die Ports ... out PORTB, TMP ; ... schreiben in R17, PINA ; von den Pins ... in R18, PINB ; ... lesen eor R17, TMP ; Exklusiv- ... eor R18, TMP ; ... verodern ; switching cpi CURRENT_GATTER, 1 breq test_PA2 ; Gatter 1 pruefen cpi CURRENT_GATTER, 2 breq test_PA5 ; Gatter 2 pruefen cpi CURRENT_GATTER, 3 breq test_PB2 ; Gatter 3 pruefen cpi CURRENT_GATTER, 4 breq test_PB5 ; Gatter 4 pruefen test_PA2: sbrs R17, PINA2 ; ist PINA2 gesetzt (unterscheidet sich PINA2 von dem erwarteten Wert)? rjmp type_match ; ... wenn nicht, naechster Test rjmp type_mismatch ; sonst: naechster Typ test_PA5: sbrs R17, PINA5 ; PINA5 wie erwartet? rjmp type_match ; nein: naechster Test rjmp type_mismatch ; sonst: naechster Typ test_PB2: sbrs R18, PINB2 ; PINB2 wie erwartet? rjmp type_match ; nein: naechster Test rjmp type_mismatch ; sonst: naechster Typ test_PB5: sbrs R18, PINB5 ; PINB5 wie erwartet? rjmp type_match ; nein: naechster Test rjmp type_mismatch ; sonst: naechster Typ type_match: ; nachster Test dec COUNTER breq test_end ; alle 4 Tests waren erfolgreich rjmp type_loop ; naechsten Test durchfuehren type_mismatch: ; nachsten Typen ausprobieren inc GATTER_TYPE cpi GATTER_TYPE, TYPE_UNKNOWN ; Abbruchbedingung breq test_end ; alle Gatter-Typen getestet dec COUNTER ; zaehler noch dekrementieren brne z_restore ; sind noch unausgefuehrte Tests verblieben? -> Z-Register korrigieren ldi COUNTER, 4 ; Test-Zaehler zuruecksetzen rjmp type_loop ; zurueck zur Schleife z_restore: lpm TMP, Z+ ; inkrementiere die Adresse im Z-Register dec COUNTER brne z_restore ; bis sie auf dem ersten Test des naechsten Typs steht ldi COUNTER, 4 rjmp type_loop test_end: ret ; Die Interrupt Service Routine soll das untere Bit des Register BLINK je Aufruf invertieren. TIMER0_COMP_ISR: push TMP ; Sichere TEMP in TMP, SREG ; Lade das SREG in TEMP push TMP ldi TMP, 1 eor BLINK, TMP pop TMP ; Hole das SREG wieder vom Stack out SREG, TMP ; Und schreibe es raus pop TMP reti ; Das Unterprogramm OUTPUT erwartet im Register R16 den Typen des IC-Bausteins (TYPE_AND|TYPE_NAND|TYPE_OR|TYPE_UNKNOWN) OUTPUT: push R16 push R17 push R18 push R19 push COUNTER ; R16 enthält den Gattertypen ldi xl, low(GATTER_TYPES) ldi xh, high(GATTER_TYPES) clr COUNTER clr R19 cpi R16, TYPE_UNKNOWN brne loop_out sbrs BLINK, 0 rjmp all_off ldi R17, 0xC0 out PORTA, R17 out PORTB, R17 ldi R17, 0xC3 out PORTC, R17 ldi R17, 0x1E out PORTD, R17 rjmp loop_out_end all_off: clr R17 out PORTA, R17 out PORTB, R17 out PORTC, R17 out PORTD, R17 rjmp loop_out_end loop_out: ld R18, x+ lsr R19 cp R18, R16 brne loop_out_ne_blink ldi R17, 0x80 add R19, R17 rjmp loop_out_ne loop_out_ne_blink: sbrc BLINK, 0 rjmp loop_out_ne ldi R17, 0x80 add R19, R17 loop_out_ne: inc COUNTER sbrs COUNTER,2 rjmp loop_out ; Ausgabe ist in den 4 MSB von R19 enthalten cpi R16, TYPE_AND brne loop_out_nand mov R17, R19 andi R17, 0xC0 out PORTB, R17 mov R17, R19 lsl R17 lsl R17 out PORTA, R17 rjmp loop_out_end loop_out_nand: cpi R16, TYPE_NAND brne loop_out_or swap R19 lsl R19 out PORTD, R19 rjmp loop_out_end loop_out_or: mov R17, R19 swap R17 or R17, R19 andi R17, 0xC3 out PORTC, R17 loop_out_end: pop COUNTER pop R19 pop R18 pop R17 pop R16 ret
Comments