banedon wrote:
- The keyboard buffer is stored in RAM between $0900 and $09FF
- It operates by storing the incoming bytes from $09FF down to $0900
- $08FF stores the keyboard buffer index/counter.
- If the counter is $FF then the buffer is empty. If it's $0 then it's full.
Ultimately a circular buffer (aka FIFO) will be more efficient, as you won't have to look at the specific index value to make decisions. With a FIFO, two indices are used: one to point to where the next datum (byte) is to be stored in the FIFO, and the other to point to where the next datum is to be gotten from the FIFO. For performance reasons, the two indices should be on zero page. At boot time, both indices would be initialized to
$00—STZ is good for that sort of thing.
The logic would go something like this:
- When a datum is to be written into the FIFO the write index is fetched, temporarily incremented and compared to the read index. If they are the same, the FIFO is full. Otherwise, the write index is decremented to what it was when fetched and used to tell the MPU where to store the datum. Following that, the write index is permanently incremented.
- When a datum is to be gotten from the FIFO the read index is fetched and compared to the write index. If they are the same, the FIFO is empty. Otherwise, the read index is used to tell the MPU from where to get the next datum. After the datum has been gotten, the read index is incremented.
In the above, "incremented" implies that an index will eventually wrap to
$00. Hence the "circular" moniker.
The read sequence could be coded as follows:
Code:
ldx read_ix ;FIFO read index
cpx writ_ix ;write index
beq next ;no data available
;
lda fifo,x ;read datum
inc read_ix ;bump read index
clc ;datum was read
;
next rts ;return to caller
In the above, a return with carry clear means a datum was fetched and returned in the accumulator. If carry is set, no data was available and the accumulator remains unchanged.
Writing to the FIFO involves a teensy bit more code, but is straightforward:
Code:
ldx writ_ix ;FIFO write index
inx ;temporarily increment it
cpx read_ix ;read index
beq next ;FIFO is full
;
dex ;realign write index &...
sta fifo,x ;write datum
inc writ_ix ;permanently bump index
clc ;datum was written
;
next rts ;return to caller
In the write function, which would be called with the datum to be written in the accumulator, a return with carry clear means the datum was written to the FIFO. If carry is set, the FIFO is full.
That's all there is to it!