Compare commits
No commits in common. "326b2f624794582b39625b7241ae02f0e8c9da6b" and "e7bd5096cda455513b45e3882bcaac024f390837" have entirely different histories.
326b2f6247
...
e7bd5096cd
4
main.s65
4
main.s65
@ -1,7 +1,7 @@
|
|||||||
.include "system/system.h65"
|
.include "system/system.h65"
|
||||||
.include "string.h65"
|
.include "string.h65"
|
||||||
.export home,homeloop
|
.export home,homeloop
|
||||||
.import keypad_printer:absolute
|
.import printer:absolute
|
||||||
.import spi_menu:absolute
|
.import spi_menu:absolute
|
||||||
|
|
||||||
.code
|
.code
|
||||||
@ -135,7 +135,7 @@ reset:
|
|||||||
lda 0
|
lda 0
|
||||||
; beq home
|
; beq home
|
||||||
cmp #'A'
|
cmp #'A'
|
||||||
jeq keypad_printer
|
jeq printer
|
||||||
cmp #'B'
|
cmp #'B'
|
||||||
jeq spi_menu
|
jeq spi_menu
|
||||||
cmp #'C'
|
cmp #'C'
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
.ifndef INCLUDE_PRINTER
|
.ifndef INCLUDE_PRINTER
|
||||||
INCLUDE_PRINTER = 1
|
INCLUDE_PRINTER = 1
|
||||||
|
|
||||||
.global keypad_printer
|
.global printer
|
||||||
.import home:absolute
|
.import home:absolute
|
||||||
|
|
||||||
.endif ; guard
|
.endif ; guard
|
@ -1,9 +1,9 @@
|
|||||||
.include "keypad_printer.h65"
|
.include "printer.h65"
|
||||||
.include "lcd.h65"
|
.include "lcd.h65"
|
||||||
.include "keypad.h65"
|
.include "keypad.h65"
|
||||||
|
|
||||||
.code
|
.code
|
||||||
.proc keypad_printer
|
.proc printer
|
||||||
jsr lcd::clear
|
jsr lcd::clear
|
||||||
@printer_loop:
|
@printer_loop:
|
||||||
jsr kp::read
|
jsr kp::read
|
@ -29,9 +29,9 @@ INCLUDE_PS2_KEYBOARD = 1
|
|||||||
.include "system.h65"
|
.include "system.h65"
|
||||||
|
|
||||||
.scope ps2kb
|
.scope ps2kb
|
||||||
Import ps2kb, init, begin_receive, scancode, status, scancode_handler
|
Import ps2kb,init,begin_receive,send_command,scancode,status,scancode_handler
|
||||||
Import ps2kb, _receive_irq_shift_reg_handler, _receive_irq_timer_handler, _send_byte, _send_irq_shift_reg_handler, _send_irq_timer_handler,
|
Import ps2kb, _receive_irq_shift_reg_handler, _receive_irq_timer_handler, _send_byte, _send_irq_shift_reg_handler, _send_irq_timer_handler,
|
||||||
Import ps2kb, send_command, send_cmd, send_data, cmd_response, response_length, FMT_CMD_FAIL
|
Import ps2kb, send_last_bits, send_cmd, send_data, key_read, prev_status
|
||||||
|
|
||||||
VIA = IO1
|
VIA = IO1
|
||||||
; Enough time must pass for 3 bits to be shifted in.
|
; Enough time must pass for 3 bits to be shifted in.
|
||||||
@ -41,152 +41,22 @@ TIMER_RECV = 230 ; 230 ms (@1MHz)
|
|||||||
; After that, the interrupt must have happened because the keyboard will pull data low.
|
; After that, the interrupt must have happened because the keyboard will pull data low.
|
||||||
; At that point, the SR needs to be set to input again
|
; At that point, the SR needs to be set to input again
|
||||||
TIMER_SEND = 230 ; 180 ms (@1MHz)
|
TIMER_SEND = 230 ; 180 ms (@1MHz)
|
||||||
|
; use RA4 to pull the clock low
|
||||||
PULL_REG = IO::RANH
|
PULL_REG = IO::RANH
|
||||||
PULL_DDR = IO::DDRA
|
PULL_DDR = IO::DDRA
|
||||||
; use RA4 to pull the clock low
|
|
||||||
PULL_MASK_CLK = %00010000
|
PULL_MASK_CLK = %00010000
|
||||||
|
; PULL_MASK_DAT = %00001000
|
||||||
; using ff because 0 is a possible data byte (set led)
|
NO_DATA = $ff ; indicates that no data byte should be send
|
||||||
NO_DATA = $ff ; indicates that no data byte should be send
|
|
||||||
NO_RESPONSE = $ff ; indicates a command did not receive a response (yet)
|
|
||||||
ACK = $fa ; successful transmission
|
|
||||||
RESEND = $fe ; unsuccessful transmission
|
|
||||||
|
|
||||||
|
|
||||||
.enum STATUS
|
.enum STATUS
|
||||||
RECEIVE_KEYS = %10000000 ; keyboard sends scancodes
|
RECEIVE_KEYS = %10000000
|
||||||
RECEIVE_ANSWER = %01000000 ; keyboard replies to a command
|
RECEIVE_ANSWER = %01000000
|
||||||
SEND_CMD = %00100000 ; host sends/sent the command byte
|
SEND_CMD = %00100000
|
||||||
SEND_DATA = %00010000 ; host sends/sent the data byte
|
SEND_DATA = %00010000
|
||||||
SEND_RECV = %00001000 ; keyboard sends additional data byte
|
SEND_CMD_WAIT = %00001000
|
||||||
SEND = SEND_CMD | SEND_DATA | SEND_RECV ; host is sending something, only used for checking status
|
|
||||||
NONE = %00000000
|
NONE = %00000000
|
||||||
.endenum
|
.endenum
|
||||||
|
|
||||||
.enum TYPEMATIC
|
|
||||||
REPEAT_MASK = %00011111 ; 00000 = 30Hz, ..., 11111 = 2Hz
|
|
||||||
DELAY250 = %00000000
|
|
||||||
DELAY500 = %00100000
|
|
||||||
DELAY750 = %01000000
|
|
||||||
DELAY1000 = %01100000
|
|
||||||
.endenum
|
|
||||||
.endscope
|
.endscope
|
||||||
|
|
||||||
; see https://wiki.osdev.org/PS/2_Keyboard
|
|
||||||
.macro ps2kb_CmdEcho
|
|
||||||
lda #$ee
|
|
||||||
ldx #ps2kb::NO_DATA
|
|
||||||
ldy #0
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_CmdSetLeds mask
|
|
||||||
lda #$ed
|
|
||||||
.ifnblank mask
|
|
||||||
ldx #mask
|
|
||||||
.endif
|
|
||||||
ldy #0
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_CmdGetScancodeSet
|
|
||||||
lda #$f0
|
|
||||||
ldx #0
|
|
||||||
ldy #1
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_CmdSetScancodeSet set
|
|
||||||
.assert set = 1 .or set = 2 .or set = 3, warning, "ps2kb_CmdSetScancodeSet: invalid scancode set"
|
|
||||||
lda #$f0
|
|
||||||
ldx #set
|
|
||||||
ldy #0
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_CmdIdentify
|
|
||||||
lda #$f2
|
|
||||||
ldx #ps2kb::NO_DATA
|
|
||||||
ldy #2
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_CmdTypematicSettings settings
|
|
||||||
lda #$f3
|
|
||||||
ldx #settings
|
|
||||||
ldy #0
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_CmdEnable
|
|
||||||
lda #$f4
|
|
||||||
ldx #ps2kb::NO_DATA
|
|
||||||
ldy #0
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_CmdDisable
|
|
||||||
lda #$f5
|
|
||||||
ldx #ps2kb::NO_DATA
|
|
||||||
ldy #0
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_CmdSetTypematic scancode
|
|
||||||
ldy #0
|
|
||||||
.ifblank scancode
|
|
||||||
lda #$f7
|
|
||||||
ldx #ps2kb::NO_DATA
|
|
||||||
.else
|
|
||||||
lda #$fb
|
|
||||||
ldx #scancode
|
|
||||||
.endif
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_CmdSetMakeRelease scancode
|
|
||||||
ldy #0
|
|
||||||
.ifblank scancode
|
|
||||||
lda #$f8
|
|
||||||
ldx #ps2kb::NO_DATA
|
|
||||||
.else
|
|
||||||
lda #$fc
|
|
||||||
ldx #scancode
|
|
||||||
.endif
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_CmdSetMake scancode
|
|
||||||
ldy #0
|
|
||||||
.ifblank scancode
|
|
||||||
lda #$f9
|
|
||||||
ldx #ps2kb::NO_DATA
|
|
||||||
.else
|
|
||||||
lda #$fd
|
|
||||||
ldx #scancode
|
|
||||||
.endif
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_CmdSelfTest
|
|
||||||
lda #$ff
|
|
||||||
ldx #ps2kb::NO_DATA
|
|
||||||
ldy #1
|
|
||||||
jsr ps2kb::send_command
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_WaitFinishCmd
|
|
||||||
:
|
|
||||||
wai
|
|
||||||
lda ps2kb::status
|
|
||||||
and #ps2kb::STATUS::SEND
|
|
||||||
bne :-
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
.macro ps2kb_PrintCmdFailed
|
|
||||||
Printf ps2kb::FMT_CMD_FAIL,ps2kb::send_cmd,ps2kb::send_data,ps2kb::cmd_response,ps2kb::cmd_response+1,ps2kb::cmd_response+2
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
|
|
||||||
.endif ; guard
|
.endif ; guard
|
||||||
|
@ -2,26 +2,22 @@
|
|||||||
.include "string.h65"
|
.include "string.h65"
|
||||||
.include "lcd.h65"
|
.include "lcd.h65"
|
||||||
.include "parity.h65"
|
.include "parity.h65"
|
||||||
Export ps2kb, init, begin_receive, scancode, status, scancode_handler
|
Export ps2kb,init,begin_receive,send_command,scancode,status,scancode_handler
|
||||||
Export ps2kb, _receive_irq_shift_reg_handler, _receive_irq_timer_handler, _send_byte, _send_irq_shift_reg_handler, _send_irq_timer_handler,
|
Export ps2kb, _receive_irq_shift_reg_handler, _receive_irq_timer_handler, _send_byte, _send_irq_shift_reg_handler, _send_irq_timer_handler,
|
||||||
Export ps2kb, send_command, send_cmd, send_data, cmd_response, response_length, FMT_CMD_FAIL
|
Export ps2kb, send_last_bits, send_cmd, send_data, key_read, prev_status
|
||||||
|
|
||||||
.bss
|
.bss
|
||||||
status: .res 1 ; current status
|
status: .res 1
|
||||||
prev_status: .res 1 ; status before sending command
|
prev_status: .res 1
|
||||||
send_last_bits: .res 1 ; last bits to load after 8 bits were shifted out
|
send_last_bits: .res 1
|
||||||
send_cmd: .res 1 ; command to send/last sent
|
send_data: .res 1
|
||||||
send_data: .res 1 ; data byte to send/last sent or NO_DATA
|
send_cmd: .res 1
|
||||||
expect_data_length: .res 1 ; number of data bytes to expect from keyboard
|
key_read: .res 2
|
||||||
response_length: .res 1 ; number of response bytes from keyboard
|
scancode: .res 1
|
||||||
cmd_response: .res 3 ; responses from keyboard
|
scancode_handler: .res 2
|
||||||
key_read: .res 2 ; first 8 bits, last 3 bits from scancode
|
|
||||||
scancode: .res 1 ; last received scancode
|
|
||||||
scancode_handler: .res 2 ; pointer to a function that handles new scancodes
|
|
||||||
|
|
||||||
.code
|
.code
|
||||||
|
|
||||||
; these are macros the save time during the interrupt handler (no jsr, rts)
|
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @macro Enable the clock signal from the keyboard
|
;; @macro Enable the clock signal from the keyboard
|
||||||
;; @modifies: A
|
;; @modifies: A
|
||||||
@ -117,14 +113,13 @@ scancode_handler: .res 2 ; pointer to a function that handles new scancod
|
|||||||
stz key_read
|
stz key_read
|
||||||
stz key_read+1
|
stz key_read+1
|
||||||
stz scancode
|
stz scancode
|
||||||
|
bit status
|
||||||
|
|
||||||
; the 3 last bits take about 230us, at @1MHz => wait 230 cycles and then the shift register
|
; the 3 last bits take about 230us, at @1MHz => wait 230 cycles and then the shift register
|
||||||
; (this could be shorter since the it takes a few cycles after the interrupt)
|
; (this could be shorter since the it takes a few cycles after the interrupt)
|
||||||
lda #<ps2kb::TIMER_RECV
|
lda #<ps2kb::TIMER_RECV
|
||||||
sta ps2kb::VIA + IO::T2CL
|
sta ps2kb::VIA + IO::T2CL
|
||||||
|
|
||||||
; set to RECEIVE_KEYS only if RECEIVE_ANSWER is not set
|
; set to RECEIVE_KEYS only if RECEIVE_ANSWER is not set
|
||||||
bit status
|
|
||||||
bvs @status_set
|
bvs @status_set
|
||||||
lda #ps2kb::STATUS::RECEIVE_KEYS
|
lda #ps2kb::STATUS::RECEIVE_KEYS
|
||||||
sta status
|
sta status
|
||||||
@ -162,7 +157,7 @@ scancode_handler: .res 2 ; pointer to a function that handles new scancod
|
|||||||
|
|
||||||
IO_DisableIRQ ps2kb::VIA, IO::IRQ::SR
|
IO_DisableIRQ ps2kb::VIA, IO::IRQ::SR
|
||||||
IO_EnableIRQ ps2kb::VIA, IO::IRQ::T2
|
IO_EnableIRQ ps2kb::VIA, IO::IRQ::T2
|
||||||
; start timer, low order count already in latch after begin_receive
|
; start timer, low order count already in latch after init
|
||||||
lda #>ps2kb::TIMER_RECV
|
lda #>ps2kb::TIMER_RECV
|
||||||
sta ps2kb::VIA + IO::T2CH
|
sta ps2kb::VIA + IO::T2CH
|
||||||
rts
|
rts
|
||||||
@ -206,68 +201,41 @@ scancode_handler: .res 2 ; pointer to a function that handles new scancod
|
|||||||
sta scancode
|
sta scancode
|
||||||
|
|
||||||
; check parity
|
; check parity
|
||||||
CalculateOddParity
|
; CalculateOddParity
|
||||||
eor key_read+1 ; if bit 0 is 1 - parity error
|
; eor key_read+1 ; if bit 0 is 1 - parity error
|
||||||
and #1 ; bit 1 is still D7
|
; and #1 ; bit 1 is still D7
|
||||||
bne @parity_error
|
; bne @parity_error
|
||||||
@handle_scancode:
|
|
||||||
|
|
||||||
; check what to do with the scancode
|
; check what to do with the scancode
|
||||||
bit status
|
bit status
|
||||||
bpl @status_not_receive_keys ; RECEIVE_KEYS
|
bcc @status_not_receive_keys
|
||||||
jmp (scancode_handler)
|
jmp (scancode_handler)
|
||||||
@status_not_receive_keys:
|
@status_not_receive_keys:
|
||||||
bvc @status_dont_handle ; RECEIVE_ANSWER
|
bvc @status_ignore
|
||||||
jmp _process_cmd_answer
|
jmp _process_cmd_answer
|
||||||
@status_dont_handle:
|
@status_ignore:
|
||||||
rts
|
rts
|
||||||
@parity_error: ; TODO handle somehow
|
@parity_error: ; TODO handle somehow
|
||||||
lda #$fe ; fe means error/resend for commands
|
lda #$ff
|
||||||
sta scancode
|
sta scancode
|
||||||
DEBUG_LED_ON 2
|
DEBUG_LED_ON 2
|
||||||
bra @handle_scancode
|
rts
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @function Send a command to the keyboard
|
;; @function Send a command to the keyboard
|
||||||
;; @details
|
|
||||||
;; No checks are done on the validity of the command and data byte.
|
|
||||||
;; You can send anything you want to the keyboard.
|
|
||||||
;; `send_command` will return immediately, as sending the command is asynchronous.
|
|
||||||
;; The command is done if `ps2kb::status & ps2kb::STATUS::SEND == 0`.
|
|
||||||
;; @section Response
|
|
||||||
;; The answers will be in the byte array ps2kb::cmd_response.
|
|
||||||
;; If the command did not have a data byte, cmd_response is:
|
|
||||||
;; - 0: command response
|
|
||||||
;; - 1: NO_RESPONSE or additional response byte (identify keyboard command only)
|
|
||||||
;; - 2: NO_RESPONSE or additional response byte (identify keyboard command only)
|
|
||||||
|
|
||||||
;; If the command did have a data byte, cmd_response is:
|
|
||||||
;; - 0: 0xFA (ACK) or 0xFE (Resend/Error)
|
|
||||||
;; - 1: 0xFA (ACK) or 0xFE (Resend/Error)
|
|
||||||
;; - 2: NO_RESPONSE or additional response byte
|
|
||||||
;;
|
|
||||||
;; If ANY of the bytes in cmd_response is 0xFE, the command failed.
|
|
||||||
;;
|
|
||||||
;; @modifies: A,X,Y
|
;; @modifies: A,X,Y
|
||||||
;; @param A: The command byte
|
;; @param A: The command byte
|
||||||
;; @param X: The data byte or NO_DATA if only the command byte should be sent
|
;; @param X: The data byte or NO_DATA if only the command byte should be sent
|
||||||
;; @param Y: The number of data bytes expected to receive. Must be one of {0, 1, 2}
|
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.proc send_command
|
.proc send_command
|
||||||
sty expect_data_length
|
|
||||||
stx send_data
|
|
||||||
stz response_length
|
|
||||||
ldy #ps2kb::NO_RESPONSE
|
|
||||||
sty cmd_response
|
|
||||||
sty cmd_response+1
|
|
||||||
sty cmd_response+2
|
|
||||||
ldy status
|
ldy status
|
||||||
sty prev_status
|
sty prev_status
|
||||||
ldy #ps2kb::STATUS::SEND_CMD
|
ldy #ps2kb::STATUS::SEND_CMD
|
||||||
sty status
|
sty status
|
||||||
sta send_cmd ; store if it needs to be resent
|
sta send_cmd ; store if it needs to be resent
|
||||||
|
stx send_data
|
||||||
jmp _send_byte
|
jmp _send_byte
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
@ -310,9 +278,8 @@ scancode_handler: .res 2 ; pointer to a function that handles new scancod
|
|||||||
lda #<ps2kb::TIMER_SEND
|
lda #<ps2kb::TIMER_SEND
|
||||||
sta ps2kb::VIA + IO::T2CL
|
sta ps2kb::VIA + IO::T2CL
|
||||||
|
|
||||||
; setup interrupt handlers
|
|
||||||
StoreDByte _send_irq_shift_reg_handler, $3000
|
StoreDByte _send_irq_shift_reg_handler, $3000
|
||||||
StoreDByte _send_irq_timer_handler, $3060
|
StoreDByte _send_irq_timer_handler, $3006
|
||||||
pla
|
pla
|
||||||
Reverse A
|
Reverse A
|
||||||
pha
|
pha
|
||||||
@ -320,7 +287,7 @@ scancode_handler: .res 2 ; pointer to a function that handles new scancod
|
|||||||
ror ; Parity -> C
|
ror ; Parity -> C
|
||||||
lda #$ff
|
lda #$ff
|
||||||
ror ; Parity -> bit 7, rest = 1
|
ror ; Parity -> bit 7, rest = 1
|
||||||
sta send_last_bits ; loaded into SR by irq handler
|
sta ps2kb::send_last_bits ; loaded into SR by irq handler
|
||||||
pla
|
pla
|
||||||
sta ps2kb::VIA + IO::SR
|
sta ps2kb::VIA + IO::SR
|
||||||
IO_EnableIRQ ps2kb::VIA, IO::IRQ::SR
|
IO_EnableIRQ ps2kb::VIA, IO::IRQ::SR
|
||||||
@ -339,7 +306,7 @@ scancode_handler: .res 2 ; pointer to a function that handles new scancod
|
|||||||
;; - start timer 2
|
;; - start timer 2
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.proc _send_irq_shift_reg_handler
|
.proc _send_irq_shift_reg_handler
|
||||||
lda send_last_bits
|
lda ps2kb::send_last_bits
|
||||||
sta ps2kb::VIA + IO::SR
|
sta ps2kb::VIA + IO::SR
|
||||||
|
|
||||||
IO_DisableIRQ ps2kb::VIA, IO::IRQ::SR
|
IO_DisableIRQ ps2kb::VIA, IO::IRQ::SR
|
||||||
@ -352,120 +319,34 @@ scancode_handler: .res 2 ; pointer to a function that handles new scancod
|
|||||||
|
|
||||||
|
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @function Setup VIA to receive the keyboard's answer
|
;; @function Send databyte or reveice the keyboards answer
|
||||||
;; @modifies: A
|
;; @modifies: A, X, Y
|
||||||
;; @details
|
;; @details
|
||||||
;; - disable timer 2 interrupts
|
;; - disable timer 2 interrupts
|
||||||
;; - pull clock low
|
;; - if send_data is zero:
|
||||||
;; - or status with RECEIVE_ANSWER
|
;; - begin_receive
|
||||||
;; - begin receive
|
;; - set status RECEIVE_ANSWER
|
||||||
|
;; - else
|
||||||
|
;; - send_byte send_data
|
||||||
|
;; - set send_data = 0
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.proc _send_irq_timer_handler
|
.proc _send_irq_timer_handler
|
||||||
lda ps2kb::VIA + IO::T2CL ; clear interrupt flag
|
lda ps2kb::VIA + IO::T2CL ; clear interrupt flag
|
||||||
IO_DisableIRQ ps2kb::VIA, IO::IRQ::T2
|
IO_DisableIRQ ps2kb::VIA, IO::IRQ::T2
|
||||||
|
|
||||||
; disable shift register
|
lda ps2kb::send_data
|
||||||
lda ps2kb::VIA + IO::ACR
|
beq @receive
|
||||||
and #<~IO::ACR_MASK::SR
|
stz ps2kb::send_data
|
||||||
sta ps2kb::VIA + IO::ACR
|
jmp _send_byte
|
||||||
|
rts
|
||||||
_DisableClock ; disable keyboard while setting up receive
|
@receive:
|
||||||
lda status
|
_DisableClock ; disable keyboard while setting up receive
|
||||||
ora #ps2kb::STATUS::RECEIVE_ANSWER
|
lda #ps2kb::STATUS::RECEIVE_ANSWER
|
||||||
sta status
|
sta ps2kb::status
|
||||||
jmp ps2kb::begin_receive
|
jmp ps2kb::begin_receive
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
;;********************************************************************************
|
.proc _process_cmd_answer
|
||||||
;; @function Process the response of a command
|
jmp ($3200)
|
||||||
;; @details
|
|
||||||
;; Stores the answer in the `ps2kb::cmd_response` array.
|
|
||||||
;; If the response is $FE or command related transmissions are done (see below),
|
|
||||||
;; no further data will be sent or received and the `ps2kb::status` takes the previous value.
|
|
||||||
;;
|
|
||||||
;; - store response
|
|
||||||
;; - if response == 0xFE -> stop
|
|
||||||
;; - if status == SEND_CMD -> send databyte
|
|
||||||
;; - if statusk
|
|
||||||
;; You can send anything you want to the keyboard.
|
|
||||||
;; `send_command` will return immediately, as sending the command is asynchronous.
|
|
||||||
;; The command is done if `ps2kb::status & ps2kb::STATUS::SEND == 0`.
|
|
||||||
;; @section Response
|
|
||||||
;; The answers will be in the byte array ps2kb::cmd_response.
|
|
||||||
;; If the command did not have a data byte, cmd_response is:
|
|
||||||
;; - 0: command response
|
|
||||||
;; - 1: NO_RESPONSE or additional response byte (identify keyboard command only)
|
|
||||||
;; - 2: NO_RESPONSE or additional response byte (identify keyboard command only)
|
|
||||||
|
|
||||||
;; If the command did have a data byte, cmd_response is:
|
|
||||||
;; - 0: 0xFA (ACK) or 0xFE (Resend/Error)
|
|
||||||
;; - 1: 0xFA (ACK) or 0xFE (Resend/Error)
|
|
||||||
;; - 2: NO_RESPONSE or additional response byte
|
|
||||||
;;
|
|
||||||
;; If ANY of the bytes in cmd_response is 0xFE, the command failed.
|
|
||||||
;;
|
|
||||||
;; @modifies: A,X,Y
|
|
||||||
;; @param A: The command byte
|
|
||||||
;; @param X: The data byte or NO_DATA if only the command byte should be sent
|
|
||||||
;; @param Y: The number of data bytes expected to receive. Must be one of {0, 1, 2}
|
|
||||||
;;********************************************************************************
|
|
||||||
.proc _process_cmd_answer
|
|
||||||
@store_response:
|
|
||||||
ldx response_length
|
|
||||||
lda scancode
|
|
||||||
sta cmd_response,x
|
|
||||||
inx
|
|
||||||
stx response_length
|
|
||||||
stz scancode
|
|
||||||
; check for resend
|
|
||||||
cmp #$fe
|
|
||||||
beq @cmd_fail
|
|
||||||
; received something useful, check state
|
|
||||||
lda status
|
|
||||||
bit #ps2kb::STATUS::SEND_CMD
|
|
||||||
bne @cmd_sent
|
|
||||||
bit #ps2kb::STATUS::SEND_DATA
|
|
||||||
bne @everything_sent
|
|
||||||
; status must be SEND_RECV
|
|
||||||
|
|
||||||
@receive_data_response:
|
|
||||||
dec expect_data_length
|
|
||||||
bmi @cmd_done ; no more expected data
|
|
||||||
rts ; wait for another data byte
|
|
||||||
|
|
||||||
@cmd_sent:
|
|
||||||
; check if a data byte needs to be sent
|
|
||||||
lda send_data
|
|
||||||
beq @send_data ; if 0 (would fall through the cmp check TODO would it??)
|
|
||||||
cmp #ps2kb::NO_DATA
|
|
||||||
beq @everything_sent ; if not NO_DATA
|
|
||||||
@send_data:
|
|
||||||
lda #ps2kb::STATUS::SEND_DATA
|
|
||||||
sta status
|
|
||||||
lda send_data
|
|
||||||
jmp ps2kb::_send_byte ; send the data
|
|
||||||
|
|
||||||
@everything_sent: ; check if additonal bytes are expected
|
|
||||||
dec expect_data_length
|
|
||||||
bmi @cmd_done ; expect_data_length was 0
|
|
||||||
lda #(ps2kb::STATUS::SEND_RECV | ps2kb::STATUS::RECEIVE_ANSWER)
|
|
||||||
sta status
|
|
||||||
rts
|
|
||||||
|
|
||||||
@cmd_fail: ; keyboard wont expect data byte/send an additional response byte
|
|
||||||
@cmd_done:
|
|
||||||
; restore previous status
|
|
||||||
lda prev_status
|
|
||||||
sta status
|
|
||||||
; disable the clock if the previous was not RECEIVE_KEYS
|
|
||||||
cmp #ps2kb::STATUS::RECEIVE_KEYS
|
|
||||||
beq @rts
|
|
||||||
_DisableClock
|
|
||||||
@rts:
|
|
||||||
rts
|
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
.rodata
|
|
||||||
;; Can be used by other programs
|
|
||||||
FMT_CMD_FAIL: .asciiz "PS/2 Cmd fail: %x-%x > %x%x%x "
|
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
;;********************************************************************************
|
|
||||||
;; @macro Use the bbs instruction by providing the bit as a mask
|
|
||||||
;; @details
|
|
||||||
;; This is useful when having a enum with bitmasks, which might change later.
|
|
||||||
;; @param mask: A byte where a single bit is set
|
|
||||||
;; @param addr: The zero page address to test
|
|
||||||
;; @param label: The label to jump to when the bit is set
|
|
||||||
;;********************************************************************************
|
|
||||||
.macro bbs mask,addr,label
|
|
||||||
.if mask = %00000001
|
|
||||||
bbs0 addr,label
|
|
||||||
.elseif mask = %00000010
|
|
||||||
bbs1 addr,label
|
|
||||||
.elseif mask = %00000100
|
|
||||||
bbs2 addr,label
|
|
||||||
.elseif mask = %00001000
|
|
||||||
bbs3 addr,label
|
|
||||||
.elseif mask = %00010000
|
|
||||||
bbs4 addr,label
|
|
||||||
.elseif mask = %00100000
|
|
||||||
bbs5 addr,label
|
|
||||||
.elseif mask = %01000000
|
|
||||||
bbs6 addr,label
|
|
||||||
.elseif mask = %10000000
|
|
||||||
bbs7 addr,label
|
|
||||||
.else
|
|
||||||
.fatal .sprintf("bbs macro got invalid mask: %x", mask)
|
|
||||||
.endif
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
;;********************************************************************************
|
|
||||||
;; @macro Use the bbr instruction by providing the bit as a mask
|
|
||||||
;; @details
|
|
||||||
;; This is useful when having a enum with bitmasks, which might change later.
|
|
||||||
;; @param mask: A byte where a single bit is set
|
|
||||||
;; @param addr: The zero page address to test
|
|
||||||
;; @param label: The label to jump to when the bit is clear
|
|
||||||
;;********************************************************************************
|
|
||||||
.macro bbr mask,addr,label
|
|
||||||
.if mask = %00000001
|
|
||||||
bbr0 addr,label
|
|
||||||
.elseif mask = %00000010
|
|
||||||
bbr1 addr,label
|
|
||||||
.elseif mask = %00000100
|
|
||||||
bbr2 addr,label
|
|
||||||
.elseif mask = %00001000
|
|
||||||
bbr3 addr,label
|
|
||||||
.elseif mask = %00010000
|
|
||||||
bbr4 addr,label
|
|
||||||
.elseif mask = %00100000
|
|
||||||
bbr5 addr,label
|
|
||||||
.elseif mask = %01000000
|
|
||||||
bbr6 addr,label
|
|
||||||
.elseif mask = %10000000
|
|
||||||
bbr7 addr,label
|
|
||||||
.else
|
|
||||||
.fatal .sprintf("bbr macro got invalid mask: 0x%x", mask)
|
|
||||||
.endif
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
;;********************************************************************************
|
|
||||||
;; @macro Use the smb instruction by providing the bit as a mask
|
|
||||||
;; @details
|
|
||||||
;; This is useful when having a enum with bitmasks, which might change later.
|
|
||||||
;; @param mask: A byte where a single bit is set
|
|
||||||
;; @param addr: The zero page address to update
|
|
||||||
;;********************************************************************************
|
|
||||||
.macro smb mask,addr
|
|
||||||
.if mask = %00000001
|
|
||||||
smb0 addr
|
|
||||||
.elseif mask = %00000010
|
|
||||||
smb1 addr
|
|
||||||
.elseif mask = %00000100
|
|
||||||
smb2 addr
|
|
||||||
.elseif mask = %00001000
|
|
||||||
smb3 addr
|
|
||||||
.elseif mask = %00010000
|
|
||||||
smb4 addr
|
|
||||||
.elseif mask = %00100000
|
|
||||||
smb5 addr
|
|
||||||
.elseif mask = %01000000
|
|
||||||
smb6 addr
|
|
||||||
.elseif mask = %10000000
|
|
||||||
smb7 addr
|
|
||||||
.else
|
|
||||||
.fatal .sprintf("smb macro got invalid mask: 0x%x", mask)
|
|
||||||
.endif
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
;;********************************************************************************
|
|
||||||
;; @macro Use the rmb instruction by providing the bit as a mask
|
|
||||||
;; @details
|
|
||||||
;; This is useful when having a enum with bitmasks, which might change later.
|
|
||||||
;; @param mask: A byte where a single bit is set
|
|
||||||
;; @param addr: The zero page address to update
|
|
||||||
;;********************************************************************************
|
|
||||||
.macro rmb mask,addr
|
|
||||||
.if mask = %00000001
|
|
||||||
rmb0 addr
|
|
||||||
.elseif mask = %00000010
|
|
||||||
rmb1 addr
|
|
||||||
.elseif mask = %00000100
|
|
||||||
rmb2 addr
|
|
||||||
.elseif mask = %00001000
|
|
||||||
rmb3 addr
|
|
||||||
.elseif mask = %00010000
|
|
||||||
rmb4 addr
|
|
||||||
.elseif mask = %00100000
|
|
||||||
rmb5 addr
|
|
||||||
.elseif mask = %01000000
|
|
||||||
rmb6 addr
|
|
||||||
.elseif mask = %10000000
|
|
||||||
rmb7 addr
|
|
||||||
.else
|
|
||||||
.fatal .sprintf("rmb macro got invalid mask: 0x%x", mask)
|
|
||||||
.endif
|
|
||||||
.endmacro
|
|
@ -8,7 +8,7 @@
|
|||||||
;; @returns Y: The number of set bits in the byte
|
;; @returns Y: The number of set bits in the byte
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.proc count_set_bits
|
.proc count_set_bits
|
||||||
ldx #9
|
ldx #8
|
||||||
ldy #0 ; number of set bits
|
ldy #0 ; number of set bits
|
||||||
@loop:
|
@loop:
|
||||||
dex
|
dex
|
||||||
|
@ -7,8 +7,6 @@ INCLUDE_UTILITY = 1
|
|||||||
.feature string_escapes
|
.feature string_escapes
|
||||||
.feature underline_in_numbers
|
.feature underline_in_numbers
|
||||||
|
|
||||||
.include "bit_macros.h65"
|
|
||||||
|
|
||||||
.macro DEBUG_LED_OFF nr
|
.macro DEBUG_LED_OFF nr
|
||||||
pha
|
pha
|
||||||
lda IO1 + IO::RA
|
lda IO1 + IO::RA
|
||||||
@ -206,6 +204,4 @@ _n_genlabel .set 0
|
|||||||
.endif
|
.endif
|
||||||
.endmacro
|
.endmacro
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.endif ; guard
|
.endif ; guard
|
||||||
|
Loading…
Reference in New Issue
Block a user