Asembler mikrokontrolerów AVR     Emulacja bramek logicznych TTL   Kompilacja


W projektach opartych o mikrokontrolery AVR, nieraz zachodzi potrzeba realizacji jakiejś funkcji logi-
cznej. Przy aplikacjach nie wymagających bramek o dużej szybkości reakcji, zamiast używać dodatko-
wych układów scalonych TTL można programowo emulować ich działanie. Poniżej znajdują się przy-
kładowe kody źródłowe asemblera, które służą do emulacji podstawowych bramek logicznych TTL.
Pierwsze linie kodu to instrukcje konfigurujące wyprowadzenia mikrokontrolera tak, aby pracowały jako
wejścia/wyjścia danej bramki. Mogą one być wykonane tylko raz, ale jak najwcześniej po włączeniu/re-
secie mikrokontrolera. Kolejne linie kodu to właściwe instrukcje emulujące zachowanie danej bramki.
Muszą one być wykonywane ciągle, dlatego należy je umieścić w głównej pętli programu lub w proce-
durze obsługi przerwania.
Oczywiście rozwiązanie takie ma pewne wady i nie w każdym projekcie da się zaimplementować. Głó-
wną wadą jest liniowe wykonywanie kodu programu, co skutkuje powstawaniem opóźnień czasowych
w obsłudze emulowanych bramek (czas reakcji na sygnały wejściowe i czas uzyskania odpowiedzi na
wyjściu bramki). W zależności od obciążenia mikrokontrolera (dużo wykonywanego kodu) oraz często-
tliwości jego taktowania (niskie zegary), opóźnienia te mogą być zbyt długie dla niektórych zastosowań.
Kolejną wadą jest zwiększanie obciążenia mikrokontrolera przez kod każdej emulowanej bramki oraz
zajmowanie kolejnych jego wyprowadzeń, których liczba jest ograniczona.

Na niepodłączonych wejściach emulowanych bramek panuje wysoki stan logiczny, wymuszony przez
włączenie wewnętrznych rezystorów podciągających (pull-up) mikrokontrolera. Bramki z wyjściem trój-
stanowym (three-state output) są aktywowane niskim stanem logicznym (negative/low enable) na wej-
ściu /OE. Aby były one aktywowane wysokim stanem logicznym (positive/high enable), należy zmienić
w kodzie linię "breq XXXXX ;skok, jeśli /OE=0" na "brne XXXXX ;skok, jeśli /OE=1".
Podana liczba linii i rozmiar dotyczy samego kodu emulującego daną bramkę (bez instrukcji konfiguru-
jących wyprowadzenia mikrokontrolera). Podana liczba cykli zegarowych potrzebna do wykonania tego
kodu, zależy od stanów logicznych na wejściach danej bramki, dlatego jest podana w zakresie od-do.

Bramki zwykłe:

Bufor (7407)
Inwerter (7404)
AND 2-wejścia (7408)
AND 3-wejścia (7411)
NAND 2-wejścia (7400)
NAND 3-wejścia (7410)
OR 2-wejścia (7432)
OR 3-wejścia
NOR 2-wejścia (7402)
NOR 3-wejścia (7427)
XOR 2-wejścia (7486)
XOR 3-wejścia
XNOR 2-wejścia (74266)
XNOR 3-wejścia
Bramki trójstanowe:

Bufor (74125)
Inwerter (74240)
AND 2-wejścia
AND 3-wejścia
NAND 2-wejścia
NAND 3-wejścia
OR 2-wejścia
OR 3-wejścia
NOR 2-wejścia
NOR 3-wejścia
XOR 2-wejścia
XOR 3-wejścia
XNOR 2-wejścia
XNOR 3-wejścia



;Bufor (7407): A=PD0, Y=PD1
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$01       ;ustawienie pinu PD1 jako wyjścia z wysokim stanem

 BUF1:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$01
          brne    BUF1a          ;skok, jeśli A=1
          cbi     PORTD,$01      ;Y=0
          rjmp    BUF1b
BUF1a:    sbi     PORTD,$01      ;Y=1
BUF1b:

;Rozmiar: 12 B, linii kodu: 6, cykli: 6-7
;Inwerter (7404): A=PD0, Y=PD1
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$01       ;ustawienie pinu PD1 jako wyjścia z wysokim stanem

 INV1:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$01
          brne    INV1a          ;skok, jeśli A=1
          sbi     PORTD,$01      ;Y=1
          rjmp    INV1b
INV1a:    cbi     PORTD,$01      ;Y=0
INV1b:

;Rozmiar: 12 B, linii kodu: 6, cykli: 6-7
;Bramka AND 2-wejścia (7408): A=PD0, B=PD1, Y=PD2
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$02       ;ustawienie pinu PD2 jako wyjścia z wysokim stanem
          
 AND2:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          cpi     R16,$03
          breq    AND2a          ;skok, jeśli A=B=1
          cbi     PORTD,$02      ;Y=0
          rjmp    AND2b
AND2a:    sbi     PORTD,$02      ;Y=1
AND2b:

;Rozmiar: 14 B, linii kodu: 7, cykli: 7-8
;Bramka AND 3-wejścia (7411): A=PD0, B=PD1, C=PD2, Y=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$03       ;ustawienie pinu PD3 jako wyjścia z wysokim stanem

 AND3:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          cpi     R16,$07
          breq    AND3a          ;skok, jeśli A=B=C=1
          cbi     PORTD,$03      ;Y=0
          rjmp    AND3b
AND3a:    sbi     PORTD,$03      ;Y=1
AND3b:

;Rozmiar: 14 B, linii kodu: 7, cykli: 7-8
;Bramka NAND 2-wejścia (7400): A=PD0, B=PD1, Y=PD2
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$02       ;ustawienie pinu PD2 jako wyjścia z wysokim stanem

 NAND2:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          cpi     R16,$03
          breq    NAND2a         ;skok, jeśli A=B=1
          sbi     PORTD,$02      ;Y=1
          rjmp    NAND2b
NAND2a:   cbi     PORTD,$02      ;Y=0
NAND2b:

;Rozmiar: 14 B, linii kodu: 7, cykli: 7-8
;Bramka NAND 3-wejścia (7410): A=PD0, B=PD1, C=PD2, Y=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$03       ;ustawienie pinu PD3 jako wyjścia z wysokim stanem
          
 NAND3:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          cpi     R16,$07
          breq    NAND3a         ;skok, jeśli A=B=C=1
          sbi     PORTD,$03      ;Y=1
          rjmp    NAND3b
NAND3a:   cbi     PORTD,$03      ;Y=0
NAND3b:

;Rozmiar: 14 B, linii kodu: 7, cykli: 7-8
;Bramka OR 2-wejścia (7432): A=PD0, B=PD1, Y=PD2
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$02       ;ustawienie pinu PD2 jako wyjścia z wysokim stanem

 OR2:     in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          breq    OR2a           ;skok, jeśli A=B=0
          sbi     PORTD,$02      ;Y=1
          rjmp    OR2b
OR2a:     cbi     PORTD,$02      ;Y=0
OR2b:

;Rozmiar: 12 B, linii kodu: 6, cykli: 6-7
;Bramka OR 3-wejścia: A=PD0, B=PD1, C=PD2, Y=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$03       ;ustawienie pinu PD3 jako wyjścia z wysokim stanem

 OR3:     in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          breq    OR3a           ;skok, jeśli A=B=C=0
          sbi     PORTD,$03      ;Y=1
          rjmp    OR3b
OR3a:     cbi     PORTD,$03      ;Y=0
OR3b:

;Rozmiar: 12 B, linii kodu: 6, cykli: 6-7
;Bramka NOR 2-wejścia (7402): A=PD0, B=PD1, Y=PD2
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$02       ;ustawienie pinu PD2 jako wyjścia z wysokim stanem

 NOR2:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          breq    NOR2a          ;skok, jeśli A=B=0
          cbi     PORTD,$02      ;Y=0
          rjmp    NOR2b
NOR2a:    sbi     PORTD,$02      ;Y=1
NOR2b:

;Rozmiar: 12 B, linii kodu: 6, cykli: 6-7
;Bramka NOR 3-wejścia (7427): A=PD0, B=PD1, C=PD2, Y=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$03       ;ustawienie pinu PD3 jako wyjścia z wysokim stanem

 NOR3:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          breq    NOR3a          ;skok, jeśli A=B=C=0
          cbi     PORTD,$03      ;Y=0
          rjmp    NOR3b
NOR3a:    sbi     PORTD,$03      ;Y=1
NOR3b:

;Rozmiar: 12 B, linii kodu: 6, cykli: 6-7
;Bramka XOR 2-wejścia (7486): A=PD0, B=PD1, Y=PD2
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$02       ;ustawienie pinu PD2 jako wyjścia z wysokim stanem

 XOR2:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          breq    XOR2a          ;skok, jeśli A=B=0
          cpi     R16,$03
          breq    XOR2a          ;skok, jeśli A=B=1
          sbi     PORTD,$02      ;Y=1
          rjmp    XOR2b
XOR2a:    cbi     PORTD,$02      ;Y=0
XOR2b:

;Rozmiar: 16 B, linii kodu: 8, cykli: 6-9
;Bramka XOR 3-wejścia: A=PD0, B=PD1, C=PD2, Y=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$03       ;ustawienie pinu PD3 jako wyjścia z wysokim stanem

 XOR3:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          breq    XOR3a          ;skok, jeśli A=B=C=0
          cpi     R16,$07
          breq    XOR3a          ;skok, jeśli A=B=C=1
          sbi     PORTD,$03      ;Y=1
          rjmp    XOR3b
XOR3a:    cbi     PORTD,$03      ;Y=0
XOR3b:

;Rozmiar: 16 B, linii kodu: 8, cykli: 6-9
;Bramka XNOR 2-wejścia (74266): A=PD0, B=PD1, Y=PD2
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$02       ;ustawienie pinu PD2 jako wyjścia z wysokim stanem

 XNOR2:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          breq    XNOR2a         ;skok, jeśli A=B=0
          cpi     R16,$03
          breq    XNOR2a         ;skok, jeśli A=B=1
          cbi     PORTD,$02      ;Y=0
          rjmp    XNOR2b
XNOR2a:   sbi     PORTD,$02      ;Y=1
XNOR2b:

;Rozmiar: 16 B, linii kodu: 8, cykli: 6-9
;Bramka XNOR 3-wejścia: A=PD0, B=PD1, C=PD2, Y=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)
          sbi     DDRD,$03       ;ustawienie pinu PD3 jako wyjścia z wysokim stanem
          
 XNOR3:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          breq    XNOR3a         ;skok, jeśli A=B=C=0
          cpi     R16,$07
          breq    XNOR3a         ;skok, jeśli A=B=C=1
          cbi     PORTD,$03      ;Y=0
          rjmp    XNOR3b
XNOR3a:   sbi     PORTD,$03      ;Y=1
XNOR3b:

;Rozmiar: 16 B, linii kodu: 8, cykli: 6-9
;Bufor trójstanowy (74125): A=PD0, Y=PD1, /OE=PD2
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)

 BUF1T:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$04
          breq    BUF1T0         ;skok, jeśli /OE=0
          cbi     DDRD,$01
          cbi     PORTD,$01      ;Y=Z (wysoka impedancja)
          rjmp    BUF1T2
BUF1T0:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$01
          brne    BUF1T1         ;skok, jeśli A=1
          cbi     PORTD,$01
          sbi     DDRD,$01       ;Y=0
          rjmp    BUF1T2
BUF1T1:   sbi     PORTD,$01
          sbi     DDRD,$01       ;Y=1
BUF1T2:

;Rozmiar: 28 B, linii kodu: 14, cykli: 9-13
;Inwerter trójstanowy (74240): A=PD0, Y=PD1, /OE=PD2
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)

 INV1T:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$04
          breq    INV1T0         ;skok, jeśli /OE=0
          cbi     DDRD,$01
          cbi     PORTD,$01      ;Y=Z (wysoka impedancja)
          rjmp    INV1T2
INV1T0:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$01
          brne    INV1T1         ;skok, jeśli A=1
          sbi     PORTD,$01
          sbi     DDRD,$01       ;Y=1
          rjmp    INV1T2
INV1T1:   cbi     PORTD,$01
          sbi     DDRD,$01       ;Y=0
INV1T2:

;Rozmiar: 28 B, linii kodu: 14, cykli: 9-13
;Bramka trójstanowa AND 2-wejścia: A=PD0, B=PD1, Y=PD2, /OE=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)

 AND2T:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$08
          breq    AND2T0         ;skok, jeśli /OE=0
          cbi     DDRD,$02
          cbi     PORTD,$02      ;Y=Z (wysoka impedancja)
          rjmp    AND2T2
AND2T0:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          cpi     R16,$03
          breq    AND2T1         ;skok, jeśli A=B=1
          cbi     PORTD,$02
          sbi     DDRD,$02       ;Y=0
          rjmp    AND2T2
AND2T1:   sbi     PORTD,$02
          sbi     DDRD,$02       ;Y=1
AND2T2:

;Rozmiar: 30 B, linii kodu: 15, cykli: 9-14
;Bramka trójstanowa AND 3-wejścia: A=PD0, B=PD1, C=PD2, Y=PD3, /OE=PD4
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$04      ;ustawienie pinu PD4 jako wejścia z wysokim stanem (pull-up)

 AND3T:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$10
          breq    AND3T0         ;skok, jeśli /OE=0
          cbi     DDRD,$03
          cbi     PORTD,$03      ;Y=Z (wysoka impedancja)
          rjmp    AND3T2
AND3T0:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          cpi     R16,$07
          breq    AND3T1         ;skok, jeśli A=B=C=1
          cbi     PORTD,$03
          sbi     DDRD,$03       ;Y=0
          rjmp    AND3T2
AND3T1:   sbi     PORTD,$03
          sbi     DDRD,$03       ;Y=1
AND3T2:

;Rozmiar: 30 B, linii kodu: 15, cykli: 9-14
;Bramka trójstanowa NAND 2-wejścia: A=PD0, B=PD1, Y=PD2, /OE=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)

 NAND2T:  in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$08
          breq    NAND2T0        ;skok, jeśli /OE=0
          cbi     DDRD,$02
          cbi     PORTD,$02      ;Y=Z (wysoka impedancja)
          rjmp    NAND2T2
NAND2T0:  in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          cpi     R16,$03
          breq    NAND2T1        ;skok, jeśli A=B=1
          sbi     PORTD,$02
          sbi     DDRD,$02       ;Y=1
          rjmp    NAND2T2
NAND2T1:  cbi     PORTD,$02
          sbi     DDRD,$02       ;Y=0
NAND2T2:

;Rozmiar: 30 B, linii kodu: 15, cykli: 9-14
;Bramka trójstanowa NAND 3-wejścia: A=PD0, B=PD1, C=PD2, Y=PD3, /OE=PD4
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$04      ;ustawienie pinu PD4 jako wejścia z wysokim stanem (pull-up)

 NAND3T:  in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$10
          breq    NAND3T0        ;skok, jeśli /OE=0
          cbi     DDRD,$03
          cbi     PORTD,$03      ;Y=Z (wysoka impedancja)
          rjmp    NAND3T2
NAND3T0:  in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          cpi     R16,$07
          breq    NAND3T1        ;skok, jeśli A=B=C=1
          sbi     PORTD,$03
          sbi     DDRD,$03       ;Y=1
          rjmp    NAND3T2
NAND3T1:  cbi     PORTD,$03
          sbi     DDRD,$03       ;Y=0
NAND3T2:

;Rozmiar: 30 B, linii kodu: 15, cykli: 9-14
;Bramka trójstanowa OR 2-wejścia: A=PD0, B=PD1, Y=PD2, /OE=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)

 OR2T:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$08
          breq    OR2T0          ;skok, jeśli /OE=0
          cbi     DDRD,$02
          cbi     PORTD,$02      ;Y=Z (wysoka impedancja)
          rjmp    OR2T2
OR2T0:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          breq    OR2T1          ;skok, jeśli A=B=0
          sbi     PORTD,$02
          sbi     DDRD,$02       ;Y=1
          rjmp    OR2T2
OR2T1:    cbi     PORTD,$02
          sbi     DDRD,$02       ;Y=0
OR2T2:

;Rozmiar: 28 B, linii kodu: 14, cykli: 9-13
;Bramka trójstanowa OR 3-wejścia: A=PD0, B=PD1, C=PD2, Y=PD3, /OE=PD4
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$04      ;ustawienie pinu PD4 jako wejścia z wysokim stanem (pull-up)

 OR3T:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$10
          breq    OR3T0          ;skok, jeśli /OE=0
          cbi     DDRD,$03
          cbi     PORTD,$03      ;Y=Z (wysoka impedancja)
          rjmp    OR3T2
OR3T0:    in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          breq    OR3T1          ;skok, jeśli A=B=C=0
          sbi     PORTD,$03
          sbi     DDRD,$03       ;Y=1
          rjmp    OR3T2
OR3T1:    cbi     PORTD,$03
          sbi     DDRD,$03       ;Y=0
OR3T2:

;Rozmiar: 28 B, linii kodu: 14, cykli: 9-13
;Bramka trójstanowa NOR 2-wejścia: A=PD0, B=PD1, Y=PD2, /OE=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)
          
 NOR2T:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$08
          breq    NOR2T0         ;skok, jeśli /OE=0
          cbi     DDRD,$02
          cbi     PORTD,$02      ;Y=Z (wysoka impedancja)
          rjmp    NOR2T2
NOR2T0:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          breq    NOR2T1         ;skok, jeśli A=B=0
          cbi     PORTD,$02
          sbi     DDRD,$02       ;Y=0
          rjmp    NOR2T2
NOR2T1:   sbi     PORTD,$02
          sbi     DDRD,$02       ;Y=1
NOR2T2:

;Rozmiar: 28 B, linii kodu: 14, cykli: 9-13
;Bramka trójstanowa NOR 3-wejścia: A=PD0, B=PD1, C=PD2, Y=PD3, /OE=PD4
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$04      ;ustawienie pinu PD4 jako wejścia z wysokim stanem (pull-up)

 NOR3T:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$10
          breq    NOR3T0         ;skok, jeśli /OE=0
          cbi     DDRD,$03
          cbi     PORTD,$03      ;Y=Z (wysoka impedancja)
          rjmp    NOR3T2
NOR3T0:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          breq    NOR3T1         ;skok, jeśli A=B=C=0
          cbi     PORTD,$03
          sbi     DDRD,$03       ;Y=0
          rjmp    NOR3T2
NOR3T1:   sbi     PORTD,$03
          sbi     DDRD,$03       ;Y=1
NOR3T2:

;Rozmiar: 28 B, linii kodu: 14, cykli: 9-13
;Bramka trójstanowa XOR 2-wejścia: A=PD0, B=PD1, Y=PD2, /OE=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)
          
 XOR2T:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$08
          breq    XOR2T0         ;skok, jeśli /OE=0
          cbi     DDRD,$02
          cbi     PORTD,$02      ;Y=Z (wysoka impedancja)
          rjmp    XOR2T2
XOR2T0:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          breq    XOR2T1         ;skok, jeśli A=B=0
          cpi     R16,$03
          breq    XOR2T1         ;skok, jeśli A=B=1
          sbi     PORTD,$02
          sbi     DDRD,$02       ;Y=1
          rjmp    XOR2T2
XOR2T1:   cbi     PORTD,$02
          sbi     DDRD,$02       ;Y=0
XOR2T2:

;Rozmiar: 32 B, linii kodu: 16, cykli: 9-15
;Bramka trójstanowa XOR 3-wejścia: A=PD0, B=PD1, C=PD2, Y=PD3, /OE=PD4
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$04      ;ustawienie pinu PD4 jako wejścia z wysokim stanem (pull-up)

 XOR3T:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$10
          breq    XOR3T0         ;skok, jeśli /OE=0
          cbi     DDRD,$03
          cbi     PORTD,$03      ;Y=Z (wysoka impedancja)
          rjmp    XOR3T2
XOR3T0:   in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          breq    XOR3T1         ;skok, jeśli A=B=C=0
          cpi     R16,$07
          breq    XOR3T1         ;skok, jeśli A=B=C=1
          sbi     PORTD,$03
          sbi     DDRD,$03       ;Y=1
          rjmp    XOR3T2
XOR3T1:   cbi     PORTD,$03
          sbi     DDRD,$03       ;Y=0
XOR3T2:

;Rozmiar: 32 B, linii kodu: 16, cykli: 9-15
;Bramka trójstanowa XNOR 2-wejścia: A=PD0, B=PD1, Y=PD2, /OE=PD3
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$03      ;ustawienie pinu PD3 jako wejścia z wysokim stanem (pull-up)
          
 XNOR2T:  in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$08
          breq    XNOR2T0        ;skok, jeśli /OE=0
          cbi     DDRD,$02
          cbi     PORTD,$02      ;Y=Z (wysoka impedancja)
          rjmp    XNOR2T2
XNOR2T0:  in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$03
          breq    XNOR2T1        ;skok, jeśli A=B=0
          cpi     R16,$03
          breq    XNOR2T1        ;skok, jeśli A=B=1
          cbi     PORTD,$02
          sbi     DDRD,$02       ;Y=0
          rjmp    XNOR2T2
XNOR2T1:  sbi     PORTD,$02
          sbi     DDRD,$02       ;Y=1
XNOR2T2:

;Rozmiar: 32 B, linii kodu: 16, cykli: 9-15
;Bramka trójstanowa XNOR 3-wejścia: A=PD0, B=PD1, C=PD2, Y=PD3, /OE=PD4
          sbi     PORTD,$00      ;ustawienie pinu PD0 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$01      ;ustawienie pinu PD1 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$02      ;ustawienie pinu PD2 jako wejścia z wysokim stanem (pull-up)
          sbi     PORTD,$04      ;ustawienie pinu PD4 jako wejścia z wysokim stanem (pull-up)

 XNOR3T:  in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$10
          breq    XNOR3T0        ;skok, jeśli /OE=0
          cbi     DDRD,$03
          cbi     PORTD,$03      ;Y=Z (wysoka impedancja)
          rjmp    XNOR3T2
XNOR3T0:  in      R16,PIND       ;odczyt stanu pinów PD0-PD7
          andi    R16,$07
          breq    XNOR3T1        ;skok, jeśli A=B=C=0
          cpi     R16,$07
          breq    XNOR3T1        ;skok, jeśli A=B=C=1
          cbi     PORTD,$03
          sbi     DDRD,$03       ;Y=0
          rjmp    XNOR3T2
XNOR3T1:  sbi     PORTD,$03
          sbi     DDRD,$03       ;Y=1
XNOR3T2:

;Rozmiar: 32 B, linii kodu: 16, cykli: 9-15