Jump to content
  • entries
  • comments
  • views

Writing the keyboard decoding routines for the 6502 computer

Sign in to follow this  


Like I mentioned in the status update, I was attempting to port WozMon to my 6502 computer, until I remembered something; I hadn't written a proper keyboard decoding routine! Well, this was mainly because I had no idea how to program something like this, and was trying to test every bit of the matrix manually to decode the key presses. That was obviously much too inefficient, and it didn't even work because there were so many lines of code, resulting in out of range branches. Not good.


To get an idea on how to write keyboard decoding routines, I took a peek into the C64 programming scene. Apparently the C64's keyboard is a pain in the ass to read without using the built in kernal routines, and I didn't understand much of the code I read. However, there was one thing I realized that had never occurred to me; I had to use tables. From here, I figured that if I could somehow have the computer calculate the X and Y coordinates of the pressed key on the matrix, I could use those values to find out which key was pressed with the table.


The first step was to draw the keyboard into an 8x8 matrix. This was trivial, as I'd originally designed the keyboard layout from an 8x8 matrix to begin with. Here's what I drew compared to the actual keyboard layout.


The number labels were later used for verifying that you could correctly calculate the memory address in which the character would be stored in using the x and y coordinate values.


Now I needed to write some code. My old non-working keyboard code had set each of the 8 "rows" high to calculate which row the pressed key was in, then cycled through each bit in that row to figure out precisely which key it was that was pressed. This time, not being an idiot, I used a counter (the X register) and some ROL instructions to cycle through each row. If the keyboard returned a value that wasn't zero, it would mean that a key in that row was pressed, so it stored the value that was returned by the keyboard and the row number (0-7) to a location in memory. Once it was done processing every row, It jumps to a subroutine that figures out what column the pressed key is in. It uses LSR instructions to send each bit to the carry, then uses BCS to test the bit. If carry is set, it jumps to a subroutine that saves the column number (0-7) to a location in memory. Once both the row and column numbers (X and Y coordinates) are calculated, the computer multiplies the row number by 8 then adds the column value to it. The computer saves that value to the X register, then loads a value from the key table, indexed by the X register. And just like that, the computer has figured out which key was pressed.


I haven't made the key table yet, so this code isn't quite functional yet. However, that's only because I don't know what kind of values the MC6847 wants for each character in its internal character ROM, and there seems to be no documentation on this anywhere (the datasheet simply says "6-bit ASCII", well, what the hell kind of 6-bit ASCII?) Once I get the video chip circuitry working (goddammit AliExpress, I want my inveters now!) in hardware I can figure it out manually, then I'll make the key table. I shall work tirelessly so I can feature the working keyboard and hopefully WozMon in the next blog entry. Before I end this entry however, here's the assembly code for the keyboard routines. (BEWARE of massive numbers of comments. I had to do this because I'd for sure forget what this code was doing within three days of not looking at it. Maybe this is overdoing it, but better safe than sorry.)


	LDA #%00000001	; each bit will be set once to detect row
	LDX #$08	; counter
	DEX		; decrement X
	STA KBOUT	; send the row test bit to the keyboard matrix
	PHA		; the RTB needs to be reused so gotta be pushed to stack
	LDA KBIN	; load the response value from keyboard
	BNE kbrowtrue	; if value is not zero then key in that row was pressed
	PLA		; if not then load RTB to accumulator
	ROL		; rotate left to set next bit high
	CPX #$00	; check if counter is zero
	BNE kbinput	; if it isn't, repeat loop
	LDX #$08	; if it is, reset counter for next subroutine
	LDA KBSTORE	; load the row value (stored in following subroutine)
	JMP kbindex	; jump to keyboard index subroutine
	STA KBSTORE	; store row value
	STX KBROW	; store row number
	PLA		; restore RTB
	ROL		; rotate left to set next bit high
	DEX		; decrement counter
	CPX #$00	; check if counter is zero
	BNE kbinput	; if it isn't, repeat loop
	LDX #$08	; if it is, reset counter for next subroutine
	LDA KBSTORE	; load the row value
	DEX		; decrement counter
	LSR		; test bit 7 (column 8)
	BCS kbcoltrue	; if it is 1, then key in that column was pressed
	CPX #$00	; check if counter is zero
	BNE kbindex	; if it isn't, repeat loop
	STX KBCOL	; store column value
	LDA KBROW	; load row number to calculate key location on table
	LDX #$08	; set counter (multiply by 8 = add 8 times)
	DEX		; decrement counter
	ADC KBROW	; add row number (times 8)
	CPX #$00	; check if counter is zero
	BNE kbdecode	; if it isn't, repeat subroutine
	ADC KBCOL	; if it is, then add the column value
	TAX		; transfer final value to X
	LDA keytable,X	; load the character corresponding to the calculated value from key table
keytable: (insert table here)

I'll see ya in the next entry.

  • Like 1
Sign in to follow this  


Recommended Comments

There are no comments to display.

Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...