[A Project to interface a PS/2 keyboard to a 68hc11 microcontroller]
Following on from the “final solution” plan described in the previous episode, the first step is to try to simulate incoming keyboard-clock interrupts.
This can be done by using a pin of the output-only PORTB on the 68hc11 directly connected back to the input-capture pin concerned, and then to drive that output pin under software control.
The green wire is the loopback from PORTB pin 2 to PORTA pin 0 (IC3). Oh, and spot the stickers – so I can remember which LED is which (it was otherwise too easy to lose track of which debug code was triggering, in which sequence).
Interrupts Don’t Happen at The Worst Possible Time
Unfortunately, in spite of performing all the required magic software incantations regarding the input-capture control-registers (TMSK1, TFLG1), and installing a jump to my IC3 ISR routine at the designated address ($00E2), no amount of twiddling PORTB pin 2 seemed to trigger the interrupt – the ISR never gets called.
The ISR itself just increments a 16-bit counter variable, which can then be displayed by the main program. The darned thing is stuck at zero.
; pin-masks for PORTB LED1 EQU $01 LED2 EQU $02 EVNT EQU $04 ; a program-drivable output-logic event pin ; can be used to simulate PS/2 kbd clock-interrupts ; if PB2 wired directly to IC3 counter FCB 0 ; 16-bit counter variable FCB 0 ; PS/2 kbd interrupt-service routine p2k_intr ldab #$01 ; acknowledge interrupt: clear IC3F flag stab TFLG2,X ldab #LED2 ; toggle LED2 bsr bptog ldd counter ; increment counter addd #1 std counter rti ; (note: also globally reenables interrupts) ; toggle specified PORTB pins ; argument: B = pin bitmask ; clobbers: B bptog eorb PORTB,X stab PORTB,X rts
I triple checked the loopback wire, the initialisation code, the ISR code, and even used BUFFALO to in-circuit disassemble the RAM contents at $00E2 (the interrupt vector), to verify that it was a long jump to the ISR code. Even comparing my code to input-capture examples in the Motorola/Freescale documentation didn’t show up any obvious omissions. Triple-checked the interrupt-vector address I has was right (from the BUFFALO documentation) – no problems there either, but still no firing.
Altering the program to allow the counter to be incremented directly, outside of the ISR, proved that my display routines and 16-bit increment code were indeed working.
Then I added two lines of code to the top of the ISR to additionally toggle the state of LED2, to provide visible evidence of the ISR being called. Still nothing doing. What the heck? This is incredibly frustrating!
It seems that sometimes “interrupts don’t happen”, and fail to do so at the “worst possible time”!
Perhaps it would be possible to trigger some other non-pin-related interrupt? The SWI instruction (software interrupt) does that, via vector $00F4. Recoding the program to install the jump-to-ISR at that vector, and to execute an SWI instruction instead of twiddling PORTB pin 2, could demontrate the ISR being called…
The program reads a command-character from the SCI, and takes the requested action thus:
- r = report value of counter (in hex)
- t = trigger software interrupt (indirectly increment counter and toggle LED2)
- 1 = directly toggle LED1
- 2 = directly toggle LED2
- q = restart BUFFALO
Hey, we now have a vectored ISR being called:
Yes, yes, it’s “cheating”, but I had to find some way to prove I can handle interrupts. Next step is to go back and try and get pin-based input-capture interrupts going. After the last 2 days of frustration, I’m not looking forward to that with much enthusiasm…
PS: If you want to inspect the full source-code of these programs and my on-chip-EEPROM-resident library, please visit http://shelldozer.im/cherryside/src.