Es ist ja nicht so, als hätte ich nicht selbst schon Interrupts gequält. Und dann beißen die halt zurück. Und so sieht eine Problemlösung in SPIN aus, die mit 8 Pins 16 Tasten und Dioden bedient. Das ist eben genau der Punkt: eine Stunde Lebenszeit ist nicht mit Geld aufzuwiegen. Und wenn dann mal so nebenbei noch ein VGA-Monitor, eine Tastatur und eine Maus, inklusive Kopfhöhrer und Mikrofon von einem Chip gemanaged wird, dann ist das eben mehr wert als 3 Euro. Man kauft sich ja ein Auto auch nicht zum Fahren, sondern als zweite Haut.

Code:
''*****************************
''*  IOMatrix 0.0             *
''*  (C) 2007 Nascma GmbH     *
''*****************************
{{ Dieses Programm bearbeitet 16 Taster und 16 Leuchtdioden in einer Matrixschaltung.
Es werden 4+4 Pins benötigt zum Treiben von Reihen und Kolonnen. Die Dioden sind von
den Reihen zu den Kolonnen geschaltet, die Schalter sind mit Widerständen 1 K in Serie
parallel zu den Dioden geschaltet. Die Reihen sind mit Widerständen 10 K nach Masse
gelegt.

Die beiden Gruppen der Pins müssen zu je 4 aufeinanderfolgen.

Die Eingänge sind entprellt.
Die Schalter werden gescannt und das Ergebnis erhöht (gedrückt) oder erniedrigt (offen)
die Variable Button (Intervallgrenzen 0 - Entprellwert). Erreicht die Variable einen
Grenzwert, wird geprüft, ob sich sich verändert hat (ButtonStatus). Falls ja, wird der
Status aktualisiert und ein Trigger ausgelöst (ButtonTrigger). Der Trigger wird
durch die verarbeitende Routine quittiert.

Die Ausgänge repräsentieren den Wert der Variablen LEDStatus.
}}
CON

  _clkmode = xtal1+pll16x
  _clkfreq = 80_000_000

  RowD = 0
  RowC = 1
  RowB = 2
  RowA = 3
  Col4 = 4
  Col3 = 5
  Col2 = 6
  Col1 = 7

  Deboun = 2  ' Zählerstand fürs Entprellen
  
VAR

  long  vga_status      'status: off/visible/invisible  read-only       (21 contiguous longs)

  byte  Button[16]
  byte  ButSta[16]
  byte  ButTog[16]
  byte  LEDSta[16]
OBJ

  vga : "vga"


PUB begin   | Index, RowIdx, ColIdx

  bytefill (@Button, 0, 64)
  dira[Col4..Col1]~~     'Spalten sind immer Ausgänge
  outa[Col4..Col1]~~     'Spalten sind immer Ausgänge
  
'  dira[8]~~ 'Trigger  nur zum testen!



  
  repeat     ' Eine Schleife auf ewig

'    outa[8] := 1               nur zum Testen, Oszi Trigger
'        waitcnt(clkfreq/5000 + cnt)        '1 ms warte               
'    outa[8] := 0
    Index := 0           ' Index geht von 0 bis 15
    repeat RowIdx from RowA to RowD ' Für die 4 Zeilen, = PinNummer
      repeat ColIdx from Col1 to Col4 ' Für die 4 Spalten, = PinNummer

        ' Taster testen
        dira[ColIdx]~~
        outa[ColIdx]~~    ' Ausgang setzen
        dira[RowIdx]~     ' Die Reihe wird gelesen
'        waitcnt(400 + cnt)        'Minimales Warten               
        if ina [RowIdx]   ' Schalter ist geschlossen!
          Button[Index] :=  0 #> Button[Index] - 1    
 '         LEDSta[Index] := LEDSta[Index] ^ %1
          
        else              ' Schalter ist offen!
          Button[Index] :=  Deboun <# Button[Index] + 1    

        case Button[Index]
          0:
                  if ButSta[Index] == 1
                    ButTog [Index] := 1
                  ButSta[Index] := 0      
          Deboun:  
                  if ButSta[Index] == 0
                    ButTog [Index] := 1
                  ButSta[Index] := 1      

        ' LEDStatus togglen
        if ButTog[Index] == 1
          ButTog[Index] := 0
          if ButSta[Index]
            LEDSta[Index] := LEDSta[Index] ^ %1
          
        ' LED schalten
        dira[RowIdx]~~
        outa[ColIdx] := LEDSta[Index]      'Ausgang setzen LOW
        outa[RowIdx] := !LEDSta[Index]
        waitcnt(clkfreq/1000 + cnt)        '1 ms warte               
        outa[RowIdx] := 0
        dira[ColIdx]~
  
        Index ++