KERNAL SCNKEY/GETIN

Basic and Machine Language

Moderator: Moderators

Post Reply
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

KERNAL SCNKEY/GETIN

Post by chysn »

The VIC-20 Programmer's Reference Guide says that this is the way to scan the keyboard and check for pressed keys, using the KERNAL:

Code: Select all

GET JSR SCNKEY
    JSR GETIN
    CMP #0
    BEQ GET
    JSR CHROUT
This is, at best, incomplete. If you just do JMP GET after the last line, the behavior starts to get really weird with most keys (usually resulting in a bunch of noise on the screen). Even if you do just want to wait for one keypress, the routine as written treats both SHIFT keys as characters. I've tried spicing the routine up by adding

Code: Select all

    LDA #0
    STA $C6 ; To clear the keyboard buffer
DEB LDA $C5 ; Wait for all keys to be released before continuing
    CMP #$40 ; ,,
    BNE DEB ; ,,
    JMP GET
This sort of works, but you have to type in a pretty unnatural style, completely disengaging a key before typing a new one.

I went to the IRQ service routine to get some tips. I thought, since the service routine is already calling SCNKEY, maybe it's a bad idea to do it again. I tried enclosing my KERNAL calls in SEI/CLI, but that didn't help. The thing that did help was getting rid of SCNKEY entirely, and just letting it happen through either the native service routine, or a replacement routine. This seems to be correct:

Code: Select all

     JSR GETIN
     CMP #0
     BEQ ETC
     JSR CHROUT
 ETC ; do other things
 
I'm curious as to why extra calls to SCNKEY result in extra keypresses registered, and the SHIFT key behavior. I should have some time to delve into it over the weekend.

However, for most purposes, I see myself continuing to just read $C5 when I care about keypresses.
VIC-20 Projects: wAx Assembler, TRBo: Turtle RescueBot, Helix Colony, Sub Med, Trolley Problem, Dungeon of Dance, ZEPTOPOLIS, MIDI KERNAL, The Archivist, Ed for Prophet-5

WIP: MIDIcast BASIC extension

he/him/his
User avatar
srowe
Vic 20 Scientist
Posts: 1340
Joined: Mon Jun 16, 2014 3:19 pm

Re: KERNAL SCNKEY/GETIN

Post by srowe »

The junk is caused by the IRQ re-entering SCNKEY, if I wrap the JSR SCNKEY with SEI/CLI I get the correct results.

I don't see the benefit of explicitly calling SCNKEY, the only time I've used it is in a cartridge startup routine because interrupts hadn't yet been enabled.
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: KERNAL SCNKEY/GETIN

Post by Mike »

chysn wrote:The VIC-20 Programmer's Reference Guide says that this is the way to scan the keyboard and check for pressed keys, using the KERNAL:

Code: Select all

GET JSR SCNKEY
    JSR GETIN
    CMP #0
    BEQ GET
    JSR CHROUT
[...]
The PRG for sure has its own share of inaccuracies and errors, but this code snippet on page 201 maybe is one of the bigger brainfarts. At least the writers should have given the necessary conditions and reasons when to read the keyboard that way.

SCNKEY is regularily called in the normal IRQ, and the sequence above only makes sense in parts of the program where interrupts are or have to be disabled for a prolonged time yet it is still necessary to read the keyboard.

A srowe writes, a call of SCNKEY in the foreground - with the normal IRQ enabled - will be disturbed by the call of SCNKEY in the interrupt. When the remainder of SCNKEY then is executed in the foreground upon return from IRQ, it will likely result in rubbish.
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: KERNAL SCNKEY/GETIN

Post by chysn »

srowe wrote: Sat Feb 19, 2022 2:28 am The junk is caused by the IRQ re-entering SCNKEY, if I wrap the JSR SCNKEY with SEI/CLI I get the correct results.
It seems like you get correct results with a cursory check. But if you play around for a couple minutes, you'll see double keypresses here and there, or a registered keypress upon release, not to mention the totally off-the-hook behavior of the space bar (being now untimed?). Even if you NOP away the CLI, it's not quite right.

It's like SCNKEY doesn't work perfectly unless it's called via IRQ...

Could it be that the routine is super-sensitive to mechanical double-presses because SCNKEY is called so much more frequently?
Mike wrote: Sat Feb 19, 2022 4:08 amThe PRG for sure has its own share of inaccuracies and errors
Yeah, surely. That's why I try these things out!
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: KERNAL SCNKEY/GETIN

Post by Mike »

chysn wrote:It's like SCNKEY doesn't work perfectly unless it's called via IRQ...
Read this as: you are not supposed to call SCNKEY from user code, unless:
  • you have disabled the standard IRQ for a prolonged time, but still want to read the keyboard (and then, as you have noticed one still gets problems if the newly assumed scan rate is much higher than 60 times a second),
  • you have installed a replacement system IRQ routine that already(!) calls SCNKEY by itself (and does not lead to an accidental call of SCNKEY by continuing at $EABF, i.e. really a true replacement!), or
  • (as srowe wrote:) you need to read the keyboard during cartridge initialisation when interrupts are still off and no IRQ has been serviced so far (and then using the VIA ports directly to check for certain keys held down is possibly the better way to do that).
Edit: See also Senior Moment With SCNKEY ... :wink:
Post Reply