Skip to content

6502 - Reaktion auf Eingangssignalen

Überblick

  • Der Zustand der Tastern kann über den VIA 6522 überwacht werden.
  • DDRx = 0 setzt den entsprechenden Pin als Eingang.
  • Durch Lesen des IRx-Registers (gleiche Adresse, wie ORx) kann der Zustand abgefragt werden.

alt: "LEDs und Taster an PORTA des VIA", w:66

PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7
BTN1 D1 BTN2 D2 BTN3 D3 BTN4 D4

Lesen des Eingangs-Registers

Erstes Beispiel

Lesen des Registers IRA und Setzen des Wertes in ORB

reset:
    ldx #$ff
    txs

    lda #(LED1 + LED2 + LED3 + LED4)
    sta DDRA
    lda #0xFF
    sta DDRB

loop:
    lda ORA
    sta ORB

    jmp loop

Resultierende Bus-Aktivität

> AB = 0x800F  R  DB = 0xAD          lda $7f01
> AB = 0x8010  R  DB = 0x01
> AB = 0x8011  R  DB = 0x7F
> AB = 0x7F01  R  DB = 0x55
> AB = 0x8012  R  DB = 0x8D          sta $7f00
> AB = 0x8013  R  DB = 0x00
> AB = 0x8014  R  DB = 0x7F
> AB = 0x7F00  w  DB = 0x55
> AB = 0x8015  R  DB = 0x4C          jmp $800f
> AB = 0x8016  R  DB = 0x0F
> AB = 0x8017  R  DB = 0x80

Bitmanipulation

  • Ziel: Wird ein Taster gedrückt, so soll die zugehörige LED leuchten.

Bitmanipulation der Taster und LED1

loop:
    lda ORA
    and #BTN1

    bne ledoff

    lda ORA
    ora #LED1
    sta ORA
    jmp loop

ledoff:
    lda ORA
    and #~LED1
    sta ORA

    jmp loop

Erweitertes Beispiel für alle LEDs mit Subroutine und Listenzugriff

ldx #0
loop:
    jsr led_btn_update
    inx
    txa
    and #3
    tax
    jmp loop

led_btn_update:
    lda ORA
    and BTNS,x
    bne ledoff
    lda ORA
    ora LEDS,x
    sta ORA
    rts
ledoff:
    lda #0xFF
    eor LEDS,x
    and ORA
    sta ORA
    rts

BTNS:
    .byte BTN1
    .byte BTN2
    .byte BTN3
    .byte BTN4
LEDS:
    .byte LED1
    .byte LED2
    .byte LED3
    .byte LED4

Interrupts

Überblick

  • Der 6502 unterstützt zwei verschiedene Interrupts
  • NMI (non-maskable interrupt)
  • IRQ (interrupt request)
  • Zu jeden dieser Interrupts gibt es ein zugehörigen Pin, wird dieser auf Masse gezogen, so kann der Interrupt ausgelöst werden.

Testprogramm für NMI und IRQ

    .org 0x8000
reset:
    ; cli
    ldx #$ff
    txs
    lda #0xFF
    sta DDRB

    lda #0
loop:
    sta ORB
    jmp loop

nmi:
    inc a
    rti

irq:
    dec a
    rti

    .org $FFFA
    .word nmi
    .word reset
    .word irq

NMI

  • Der NMI kann nicht unterbunden werden.
  • Bei einem H→L-Übergang am NMIB-Pin wird der NMI aktiv.
  • Die Adresse der Interrupt-Service-Routine (ISR) wird in den Speicherzellen 0xFFFA und 0xFFFB abgelegt.
  • Zuvor müssen die Rückkehradresse (PCL und PCH) und den der Prozessorstatus in im Stapel abgelegt werden.
  • Die ISR wird durch die RTI-Anweisung (return from interrupt) verfassen.
  • PC und Status-Register werden wiederhergestellt.

Bus-Aktivität während eines NMI

> AB = 0x800A  R  DB = 0x8D          sta $7f00
> AB = 0x800B  R  DB = 0x00    NMIB
> AB = 0x800C  R  DB = 0x7F
> AB = 0x7F00  w  DB = 0x17
> AB = 0x800D  R  DB = 0x4C          jmp $800a
> AB = 0x800D  R  DB = 0x4C
> AB = 0x01FF  w  DB = 0x80
> AB = 0x01FE  w  DB = 0x0D
> AB = 0x01FD  w  DB = 0x67
> AB = 0xFFFA  R  DB = 0x10
> AB = 0xFFFB  R  DB = 0x80
> AB = 0x8010  R  DB = 0x1A          ina A
> AB = 0x8011  R  DB = 0x40
> AB = 0x8011  R  DB = 0x40          rti
> AB = 0x8012  R  DB = 0x3A
> AB = 0x01FC  R  DB = 0x80
> AB = 0x01FD  R  DB = 0x67
> AB = 0x01FE  R  DB = 0x0D
> AB = 0x01FF  R  DB = 0x80
> AB = 0x800D  R  DB = 0x4C          jmp $800a
> AB = 0x800E  R  DB = 0x0A

IRQ

  • Der IRQ-Interrupt muss durch das entsprechenden Wert im Prozessor-Status aktiviert werden.
    alt: "6502 Status Register", w:50,  src: "W65C02 Datenblatt, S. 8"
  • Es wird solange die zugehörige ISR ausgeführt, wie IRQB auf L-Pegel ist.
  • Der zugehörige Interrupt-Vektor befindet sich in den Speicherzellen 0xFFFE, 0xFFFF

Bus-Aktivität während eines IRQ

> AB = 0x800E  R  DB = 0x4C          jmp $800b
> AB = 0x800F  R  DB = 0x0B
> AB = 0x8010  R  DB = 0x80    IRQB
> AB = 0x800B  R  DB = 0x8D    IRQB  sta $7f00
> AB = 0x800B  R  DB = 0x8D    IRQB
> AB = 0x01FF  w  DB = 0x80
> AB = 0x01FE  w  DB = 0x0B
> AB = 0x01FD  w  DB = 0x63
> AB = 0xFFFE  R  DB = 0x13
> AB = 0xFFFF  R  DB = 0x80
> AB = 0x8013  R  DB = 0x3A          dea A
> AB = 0x8014  R  DB = 0x40
> AB = 0x8014  R  DB = 0x40          rti
> AB = 0x8015  R  DB = 0x00
> AB = 0x01FC  R  DB = 0x80
> AB = 0x01FD  R  DB = 0x63
> AB = 0x01FE  R  DB = 0x0B
> AB = 0x01FF  R  DB = 0x80
> AB = 0x800B  R  DB = 0x8D          sta $7f00

Pin-Interrupts durch den 6522

  • Der 6522 kann aus 7 verschiedenen Quellen einen Interrupt erzeugen und gibt diesen durch das Setzen der IRQB-Leitung an den 6502.
  • Hierfür wird das IFR (Interrupt Flag Register) (0x0D) und das IER (Interrupt Enable Register) (0x0E) benötigt.

alt: "6522 Interrupt Flag Register", src: "W65C22 Datenblatt, S. 26", w:50

alt: "6522 Interrupt Enable Register", src: "W65C22 Datenblatt, S. 27", w:50

  • Die vier Taster sind mit den vier Interrupt-Pins des 6522 verbunden
Taster Port A Interrupt
BTN1 PA0 CA1
BTN2 PA2 CA2
BTN3 PA4 CB1
BTN4 PA6 CB2
  • Im PCR (Peripheral Control Register) (0x0C) wird die Interrupt-Flanke eingestellt.

alt: "6522 Peripheral Control Register", src: "W65C22 Datenblatt, S. 13", w:50

Pin-Interrupts durch Taster 1

ORB = 0x7F00
ORA = 0x7F01
DDRB = 0x7F02
DDRA = 0x7F03
PCR = 0x7F0C
IFR = 0x7F0D
IER = 0x7F0E

CA1 = 0x02
CA2 = 0x01
CB1 = 0x10
CB2 = 0x08

    .org 0x8000
reset:
    cli
    ldx #$ff
    txs

    lda #0xFF
    sta DDRB

    lda #0
    sta PCR
    sta IFR

    lda #0x82
    sta IER

    lda #0
    sta ORB
loop:
    jmp loop

irq:
    lda IFR
    and #CA1
    beq exit_irq
    inc ORB
    bit ORA
exit_irq:
    rti

    .org $FFFA
    .word reset
    .word reset
    .word irq