Compare commits

...

9 Commits

Author SHA1 Message Date
b60ff7be12 wip keyboard 2023-12-31 01:59:06 +01:00
2bfae04f50 use additional buffer size var 2023-12-31 01:58:47 +01:00
ff4e284f26 add byte reverse 2023-12-31 01:57:52 +01:00
5767133ae3 add byte reverse 2023-12-31 01:57:46 +01:00
dce5a43804 add printf 2023-12-31 01:57:05 +01:00
b65a0249a5 use masked writes for RA 2023-12-31 01:56:42 +01:00
de098dd9c6 define spi mem 2023-12-31 01:56:02 +01:00
498b9803f1 Reapply "add keyboard"
This reverts commit 45dce42475.
2023-12-27 21:40:14 +01:00
45dce42475 Revert "add keyboard"
This reverts commit 302e49a9f7.
2023-12-27 21:38:10 +01:00
15 changed files with 629 additions and 242 deletions

View File

@ -3,7 +3,7 @@ MEMORY {
# RAM: start = $0100, size = $5eff, type = rw, file = "", fill = yes; # RAM: start = $0100, size = $5eff, type = rw, file = "", fill = yes;
STACK: start = $0100, size = $0100, type = rw, file = "", fill = yes; STACK: start = $0100, size = $0100, type = rw, file = "", fill = yes;
RAM: start = $0200, size = $4e00, type = rw, file = "", fill = yes; RAM: start = $0200, size = $4e00, type = rw, file = "", fill = yes;
SPI: start = $5000, size = $1000, type = rw, file = "../spi.bin", fill = no; SPI: start = $5000, size = $1000, type = rw, file = "../spi.bin", fill = no, define = yes;
VIA1: start = $6000, size = $000f, type = rw, file = "", fill = yes; VIA1: start = $6000, size = $000f, type = rw, file = "", fill = yes;
VIA2: start = $7000, size = $000f, type = rw, file = "", fill = yes; VIA2: start = $7000, size = $000f, type = rw, file = "", fill = yes;
ROM: start = $8000, size = $8000, type = ro, file = %O, fill = yes; ROM: start = $8000, size = $8000, type = ro, file = %O, fill = yes;
@ -15,8 +15,8 @@ SEGMENTS {
ZEROPAGE: load = RAM_ZP, type = bss, start = $0; ZEROPAGE: load = RAM_ZP, type = bss, start = $0;
BSS: load = RAM, type = bss; BSS: load = RAM, type = bss;
CODE: load = ROM, type = ro; CODE: load = ROM, type = ro;
RODATA: load = ROM, type = ro; RODATA: load = ROM, type = ro, align = $800;
RESET_VECTOR: load = ROM, type = ro, start = $FFFA; RESET_VECTOR: load = ROM, type = ro, start = $FFFA;
SPI: load = SPI, type = rw, define = yes; SPI: load = SPI, type = rw;
TEST: load = TEST,type = rw; TEST: load = TEST,type = rw;
} }

View File

@ -1,34 +1,11 @@
.include "system/system.h65" .include "system/system.h65"
.include "string.h65"
.export home,homeloop .export home,homeloop
.import printer:absolute .import printer:absolute
.import spi_menu:absolute .import spi_menu:absolute
.code .code
.macro DEBUG_LED_OFF nr
pha
lda IO1 + IO::RA
.if nr = 0
and #%11111110
.else
and #%11111101
.endif
sta IO1 + IO::RA
pla
.endmacro
.macro DEBUG_LED_ON nr
pha
lda IO1 + IO::RA
.if nr = 0
ora #%00000001
.else
ora #%00000010
.endif
sta IO1 + IO::RA
pla
.endmacro
;******************************************************************************** ;********************************************************************************
; Modules ; Modules
;******************************************************************************** ;********************************************************************************
@ -62,12 +39,14 @@ nmi:
rti rti
irq: irq:
; read IRFs, while bit 7 ist set handle interrupts ; read IRFs, while bit 7 ist set handle interrupts
; DEBUG_LED_ON 2
@irq_io1: @irq_io1:
lda IO1 + IO::IFR lda IO1 + IO::IFR
sta irq_via_ifr sta irq_via_ifr
bbr7 irq_via_ifr,@irq_io1 ; skip bbr7 irq_via_ifr,@irq_io2 ; skip
bbs2 irq_via_ifr,@irq_kb1 ; shit reg -> first 8 bits bbs2 irq_via_ifr,@irq_kb1 ; shit reg -> first 8 bits
bbs5 irq_via_ifr,@irq_kb2 ; timer -> last 3 bits bbs5 irq_via_ifr,@irq_kb2 ; timer -> last 3 bits
bra @irq_unknown
@irq_io2: @irq_io2:
lda IO2 + IO::IFR lda IO2 + IO::IFR
sta irq_via_ifr sta irq_via_ifr
@ -75,6 +54,7 @@ irq:
bbs2 irq_via_ifr,@irq_spi_p ; check SR bbs2 irq_via_ifr,@irq_spi_p ; check SR
bbs1 irq_via_ifr,@irq_keypad ; check CA1 bbs1 irq_via_ifr,@irq_keypad ; check CA1
@irq_unknown:
; this SHOULD never be reached ; this SHOULD never be reached
jsr lcd::clear jsr lcd::clear
Print "Unknown IRQ" Print "Unknown IRQ"
@ -87,13 +67,16 @@ irq:
jsr kp::read_irq jsr kp::read_irq
bra @irq_return bra @irq_return
@irq_spi_p: @irq_spi_p:
JsrIndirect (spi_p::irq_handler), @irq_return jsr spi_p::irq_read_byte
bra @irq_return
; jmp (spi_p::irq_handler)
; JsrIndirect (spi_p::irq_handler), @irq_return
@irq_kb1: @irq_kb1:
Print "$3000" ; Print "$3000"
jsr $3000 jsr $3000
bra @irq_return bra @irq_return
@irq_kb2: @irq_kb2:
Print "$3100" ; Print "$3100"
jsr $3100 jsr $3100
bra @irq_return bra @irq_return
; @irq_dht: ; @irq_dht:
@ -114,25 +97,20 @@ reset:
sta IO1 + IO::DDRA sta IO1 + IO::DDRA
DEBUG_LED_OFF 0 DEBUG_LED_OFF 0
DEBUG_LED_OFF 1 DEBUG_LED_OFF 1
DEBUG_LED_OFF 1
jsr kp::init jsr kp::init
SetCustomChar chars::CAT,0 DEBUG_LED_ON 0
SetCustomChar chars::SMILEY,1
SetCustomChar chars::SMILEY_XD,2
jsr spi_p::init
DEBUG_LED_ON 1
; ; INIT DHT ; SetCustomChar chars::CAT,0
; lda #%11000010 ; enable interrupt for Timer 1 and CA1 on IO2 ; SetCustomChar chars::SMILEY,1
; sta IER2 ; SetCustomChar chars::SMILEY_XD,2
; lda #%00111111 ; set Timer 1 to interrupt when loaded
; and ACR2 ; DEBUG_LED_ON 2
; sta ACR2
; lda #%00000001 ; set PCR2 bit 0 CA1 pos edge interrupt
; ora PCR2
; sta PCR2
; stz DHT_STATUS
; enable interrupts ; enable interrupts
cli cli
@ -170,9 +148,14 @@ reset:
cmp #'5' cmp #'5'
beq @debug1_off beq @debug1_off
cmp #'7' cmp #'7'
beq @debug2_on
cmp #'8'
beq @debug2_off
cmp #'9'
beq @print_rb beq @print_rb
cmp #'*' ; print home menu again if not visible (message 1 and 2 jmp to home) cmp #'*' ; print home menu again if not visible (message 1 and 2 jmp to home)
beq home beq home
wai
jmp @loop jmp @loop
@debug0_off: @debug0_off:
@ -187,6 +170,12 @@ reset:
@debug1_on: @debug1_on:
DEBUG_LED_ON 1 DEBUG_LED_ON 1
jmp @loop jmp @loop
@debug2_off:
DEBUG_LED_OFF 2
jmp @loop
@debug2_on:
DEBUG_LED_ON 2
jmp @loop
@print_rb: @print_rb:
jsr lcd::clear jsr lcd::clear
Print str_io2 Print str_io2
@ -215,10 +204,10 @@ message_1:
.byte " **** " .byte " **** "
.asciiz "www.quintern.xyz" .asciiz "www.quintern.xyz"
message_2: message_2:
.byte " Hello " .byte "0123456789=!?#+*"
.byte " there " .byte "ABCDEFGHIJKLMNOP"
.byte " <3 " .byte "QRSTUVWXYZÖÄÜß-_"
.asciiz "================" .asciiz "{[(<>)]}$%&/,;.:"
message_menu: message_menu:
.byte "<A> Printer " .byte "<A> Printer "
; .byte "<B> Temperatur " ; .byte "<B> Temperatur "

View File

@ -27,13 +27,27 @@ status_str: .res 17 ; 16 + null
beq @status_ERROR beq @status_ERROR
cmp #spi_p::STATUS::DONE cmp #spi_p::STATUS::DONE
beq @status_DONE beq @status_DONE
bra @status_XFER cmp #spi_p::STATUS::XFER
beq @status_XFER
cmp #spi_p::STATUS::XFER_SIZEL
beq @status_XFER_SIZEL
cmp #spi_p::STATUS::XFER_SIZEH
beq @status_XFER_SIZEH
@status_UNKNOWN:
lda #'?'
bra @update_status_end
@status_ERROR: @status_ERROR:
lda #'E' lda #'E'
bra @update_status_end bra @update_status_end
@status_DONE: @status_DONE:
lda #'O' lda #'O'
bra @update_status_end bra @update_status_end
@status_XFER_SIZEL:
lda #'1'
bra @update_status_end
@status_XFER_SIZEH:
lda #'2'
bra @update_status_end
@status_XFER: @status_XFER:
lda #'X' lda #'X'
@update_status_end: @update_status_end:
@ -42,9 +56,10 @@ status_str: .res 17 ; 16 + null
@print_status: @print_status:
lda #lcd::LINE4 lda #lcd::LINE4
jsr lcd::set_position jsr lcd::set_position
Strf "%x%xb Status: %c",status_str,trans_bytes+1,trans_bytes,status_char Strf "%x%x/%x%x|%x%x|%c",status_str,trans_bytes+1,trans_bytes,spi_p::recv_size+1,spi_p::recv_size,spi_p::buffer_size+1,spi_p::buffer_size,status_char
PrintNC status_str PrintNC status_str
@loop: @loop:
wai
; check if a byte has been transferred ; check if a byte has been transferred
@check_received: @check_received:
lda spi_p::recv_bytes lda spi_p::recv_bytes
@ -53,8 +68,8 @@ status_str: .res 17 ; 16 + null
@byte_received: @byte_received:
sta trans_bytes sta trans_bytes
lda spi_p::recv_bytes+1 lda spi_p::recv_bytes+1
lda trans_bytes+1 sta trans_bytes+1
bra @print_status jmp @update_status
@read_keypad: @read_keypad:
lda kp::_DEBUG_VAL lda kp::_DEBUG_VAL
beq @loop beq @loop
@ -70,7 +85,9 @@ status_str: .res 17 ; 16 + null
beq @spi_end beq @spi_end
cmp #'C' cmp #'C'
beq @spi_jump beq @spi_jump
bra @update_status ; any other key cmp #'D'
beq @spi_jump2
jmp @update_status ; any other key
@spi_begin: @spi_begin:
lda #<CODE_START lda #<CODE_START
sta ARG0 sta ARG0
@ -83,15 +100,20 @@ status_str: .res 17 ; 16 + null
jsr spi_p::begin_read jsr spi_p::begin_read
jmp @print_menu jmp @print_menu
@spi_end: @spi_end:
jsr spi_p::end jsr spi_p::end_read
jmp @print_menu jmp @print_menu
@spi_jump: @spi_jump:
jsr spi_p::end jsr spi_p::end_read
jsr lcd::clear jsr lcd::clear
Print START Print "---START SPI---"
jmp CODE_START jmp CODE_START
@spi_jump2:
jsr spi_p::end_read
jsr lcd::clear
Printf " >>> %x%x >>> ", spi_p::buffer_ptr+1, spi_p::buffer_ptr
jmp (spi_p::buffer_ptr)
@return_home: @return_home:
jsr spi_p::end jsr spi_p::end_read
jmp home jmp home
.endproc .endproc
@ -101,6 +123,5 @@ MENU:
.byte "B> Stop Transfer" .byte "B> Stop Transfer"
.asciiz "C> Jump Home <*" .asciiz "C> Jump Home <*"
; .asciiz "0b0p Status: X" ; .asciiz "0b0p Status: X"
FMT_STATUS: .asciiz "%x%xb Status:%x"
BEGIN: .asciiz "---BEGIN SPI---" BEGIN: .asciiz "---BEGIN SPI---"
START: .asciiz "---START SPI---" START: .asciiz "---START SPI---"

View File

@ -20,16 +20,10 @@ CODE_START:
jsr lcd::clear jsr lcd::clear
lda #'$' lda #'$'
jsr lcd::print_char jsr lcd::print_char
; jmp homeloop
; stz kp::_DEBUG_VAL DEBUG_LED_OFF 0
; @loop: DEBUG_LED_OFF 1
; lda kp::_DEBUG_VAL DEBUG_LED_OFF 2
; beq @loop
; stz kp::_DEBUG_VAL
; cmp #'*'
; jeq homeloop
; jsr lcd::print_char
; bra @loop
lda #<kb_irq1 lda #<kb_irq1
sta ARG0 sta ARG0
@ -39,7 +33,7 @@ CODE_START:
sta ARG2 sta ARG2
lda #>$3000 lda #>$3000
sta ARG3 sta ARG3
ldy #20 ldy #10
jsr memcopy jsr memcopy
lda #<kb_irq2 lda #<kb_irq2
@ -50,16 +44,16 @@ CODE_START:
sta ARG2 sta ARG2
lda #>$3100 lda #>$3100
sta ARG3 sta ARG3
ldy #20 ldy #10
jsr memcopy jsr memcopy
lda #'?'
jsr lcd::print_char
; PrintNC $3000 ; PrintNC $3000
jsr kb::init jsr kb::init
stz kb::status
lda #'%' lda #'%'
jsr lcd::print_char jsr lcd::print_char
@ -67,8 +61,41 @@ CODE_START:
ldy #0 ldy #0
@loop: @loop:
wai
lda kb::scancode
beq @noscancode
jsr process_scancode
stz kb::scancode
lda char
beq @onlykeycode
Strf fmt_codechar,out_str,keycode,kb::status,char
PrintNC out_str
stz char
stz keycode
bra @noscancode
@onlykeycode:
lda keycode
beq @noscancode
Strf fmt_code,out_str,keycode,keycode_flags
PrintNC out_str
stz keycode
@noscancode:
bbr5 kb::status, @shift_off
@shift_on:
DEBUG_LED_ON 0
bra @check_caps
@shift_off:
DEBUG_LED_OFF 0
@check_caps:
bbr4 kb::status, @caps_off
@caps_on:
DEBUG_LED_ON 2
bra @read_keypad
@caps_off:
DEBUG_LED_OFF 2
@read_keypad:
lda kp::_DEBUG_VAL lda kp::_DEBUG_VAL
beq @loop jeq @loop
stz kp::_DEBUG_VAL stz kp::_DEBUG_VAL
cmp #'*' cmp #'*'
jeq homeloop jeq homeloop
@ -85,125 +112,45 @@ CODE_START:
cmp #'C' cmp #'C'
beq @lC beq @lC
jsr lcd::print_char jsr lcd::print_char
bra @loop jmp @loop
@l1: @l1:
; jsr irq_on_shift_reg ; jsr irq_on_shift_reg
jsr $3000 jsr $3000
lda #'*' lda #'*'
jsr lcd::print_char jsr lcd::print_char
bra @loop jmp @loop
@l2: @l2:
; jsr irq_on_timer ; jsr irq_on_timer
jsr $3100 jsr $3100
lda #'#' lda #'#'
jsr lcd::print_char jsr lcd::print_char
bra @loop jmp @loop
@l3: @l3:
lda $3000,y lda $3000,y
jsr lcd::print_char jsr lcd::print_char
iny iny
bra @loop jmp @loop
@lA: @lA:
lda kb::KB_IO + IO::SR lda kb::KB_IO + IO::SR
jsr lcd::print_char jsr lcd::print_char
bra @loop jmp @loop
@lB: @lB:
Strf fmt_str, out_str, kb::keycode ; Printf "kc%x;", out_str, kb::scancode
jsr lcd::clear
ldx out_idx
lda #0
sta out_str,x
Print out_str Print out_str
bra @loop stz out_idx
jmp @loop
@lC: @lC:
jsr lcd::clear jsr lcd::clear
bra @loop jmp @loop
; .proc kbinit
; lda #'['
; jsr lcd::print_char
; ; - use the shift register interrupts to read the first 8 bits
; ; set shift register to shift in under external clock on CB1
; ; - configure timer for timing the read of the last 3 bits
; ; timer 2 one shot mode is sufficient, leaves T1 available
; lda #(IO::ACR::SR_SIN_PHIE | IO::ACR::T2_IRQ_LOAD)
; tsb kb::KB_IO + IO::ACR
; ; the 3 last bits take about 230us, at @1MHz => wait 230 cycles and then the shift register
; lda #230
; sta kb::KB_IO + IO::T2CL
; stz key_read
; stz key_read+1
; ; enable SR interrupts
; lda #(IO::IRQ::IRQ | IO::IRQ::SR)
; sta kb::KB_IO + IO::IER
; ; load SR to reset
; lda kb::KB_IO + IO::SR
; lda #']'
; jsr lcd::print_char
; rts
; .endproc
; ;; @details
; ;; IO::SR has to be read before the next bit is shifted in, which happens ~75us after the irq
; ;; at 1MHz, handlings this interrupt takes about 50us (without any additional debug code), so it should work
; .proc irq_on_shift_reg
; ; lda #'{'
; ; jsr lcd::print_char
; lda kb::KB_IO + IO::SR
; sta key_read
; stz kb::KB_IO + IO::SR
; ; disable SR interrupts
; lda #IO::IRQ::SR
; sta kb::KB_IO + IO::IER
; ; enable timer interrupts
; lda #(IO::IRQ::IRQ | IO::IRQ::T2)
; sta kb::KB_IO + IO::IER
; ; start timer
; lda #1
; sta kb::KB_IO + IO::T2CH
; ; lda #'}'
; ; jsr lcd::print_char
; rts
; .endproc
.proc irq_timer_handler
; lda #'<'
; jsr lcd::print_char
lda kb::KB_IO + IO::SR
sta kb::key_read + 1
lda kb::KB_IO + IO::T2CL ; clear interrupt flag
; disable timer interrupts
lda #(IO::IRQ::T2)
sta kb::KB_IO + IO::IER
; enable shift register interrupts
lda #(IO::IRQ::IRQ | IO::IRQ::SR)
sta kb::KB_IO + IO::IER
; reset SR
stz kb::KB_IO + IO::SR
; lda #'|'
; rotate bit 2 (last bit of keycode) into the carry
ror
ror
ror
lda kb::key_read ; not affecting carry
rol ; rotate carry into byte, rotate startbit into carry
; TODO byte is inverted, maybe consider wasting 256 bytes for a bit reverse lookup table?
sta kb::keycode
Strf fmt_str2, out_str, kb::keycode, kb::key_read, kb::key_read+1
PrintNC out_str
stz kb::key_read
stz kb::key_read+1
rts
.endproc
; key_read: .res 2 ; key_read: .res 2
; keycode: .res 1 ; scancode: .res 1
kb_irq1: kb_irq1:
; lda #'!' ; lda #'!'
; jsr lcd::print_char ; jsr lcd::print_char
@ -216,13 +163,142 @@ kb_irq2:
; lda #'?' ; lda #'?'
; jsr lcd::print_char ; jsr lcd::print_char
; jsr kb::on_timer_irq ; jsr kb::on_timer_irq
jsr irq_timer_handler jsr kb::irq_timer_handler
; lda #';' ; lda #';'
; jsr lcd::print_char ; jsr lcd::print_char
rts rts
.byte '@' .byte '@'
out_str: .res 40 .proc process_scancode
fmt_str: .asciiz "kc%x;" ; DEBUG_LED_OFF 1
fmt_str2: .asciiz "kc%x-%x-%x; " ; check how this scancode needs to be interpreted
ldx kb::scancode
bit kb::status
jmi release_key ; bit 7 set
bvs @twobytecode ; bit 6 set
; DEBUG_LED_ON 1
; check mods
cpx #kb::K_RELEASE
beq @code_release
cpx #kb::K::LEFTSHIFT
beq @code_shift
cpx #kb::K::RIGHTSHIFT
beq @code_shift
cpx #kb::K_TWOBYTE
beq @code_twobytecode
cpx #kb::K::CAPSLOCK
beq @code_capslock
; a real keycode and not a released keycode, twobyte or release scancode
stz keycode_flags
stx keycode
cmp #$62 ; $61 is the largest ascii scancode
bcs @special
bbs5 kb::status,@modshift ; if shift active
@nomod:
lda kb::CHARS_NOMOD,x
beq @special
@char: ; order which is fastet most of the time (lowercase characters)
sta char
rts
@modshift:
lda kb::CHARS_MODSHIFT,x
bne @char
@special:
rts
@code_release: ; set release
smb7 kb::status
rts
@code_twobytecode: ; set twobytecode
smb6 kb::status
rts
@code_shift: ; process shift
bbs4 kb::status, @unset_shift ; unset shift when capslock is on
@set_shift:
smb5 kb::status
rts
@unset_shift:
rmb5 kb::status
rts
@code_capslock: ; toggle capslock & shift
bbs1 kb::status, @rts ; ignore if held
lda kb::status
ora #(kb::STATUS::CAPSLOCK_HELD)
; toggle and capslock shift
eor #(kb::STATUS::CAPSLOCK | kb::STATUS::SHIFT)
sta kb::status
rts
@code_rightalt: ; set rightalt
smb3 kb::status
rts
@code_numlock: ; set numlock
smb2 kb::status
rts
@twobytecode:
rmb6 kb::status ; unset twobytecode
; check mods
cpx #kb::K2::RIGHTALT
beq @code_rightalt
lda #kb::STATUS::TWOBYTE
sta keycode_flags
stx keycode
@rts:
rts
.endproc
;; @param S: The status register must be set through `bit kb::status`
;; @param X: The scancode
.proc release_key
bvs @twobytecode
rmb7 kb::status
; check mods
cpx #kb::K_TWOBYTE
beq @code_twobytecode
cpx #kb::K::LEFTSHIFT
beq @code_shift
cpx #kb::K::RIGHTSHIFT
beq @code_shift
cpx #kb::K::CAPSLOCK
beq @code_capslock
; no need to process capslock - it gets toggled when pressed
rts
@code_twobytecode: ; unset special
rmb6 kb::status
rts
@code_shift: ; process shift
bbs4 kb::status, @code_shift_caps ; set shift when capslock is on
rmb5 kb::status ; unset if capslock is off
rts
@code_shift_caps:
smb5 kb::status
rts
@code_capslock: ; unset CAPSLOCK_HELD
rmb1 kb::status
rts
@code_rightalt: ; unset rightalt
rmb3 kb::status
rts
@code_numlock: ; unset numlock
rmb2 kb::status
rts
@twobytecode:
rmb6 kb::status ; unset twobytecode
; check mods
cpx #kb::K2::RIGHTALT
beq @code_rightalt
rts
.endproc
out_idx: .res 1
out_str: .res 40
char: .res 1
keycode: .res 1
keycode_flags: .res 1
fmt_codechar: .asciiz "%x %x %c "
fmt_code: .asciiz "%x %x "

View File

@ -3,7 +3,7 @@
;; @type drive ;; @type drive
;; @details: ;; @details:
;; Support for a PS2 Keyboard using the shift register of a 6522 VIA ;; Support for a PS2 Keyboard using the shift register of a 6522 VIA
;; Pressing a key causes 11 bits to be sent: 1 start - 8 keycode - 1 parity - 1 stop ;; Pressing a key causes 11 bits to be sent: 1 start - 8 scancode - 1 parity - 1 stop
;; The VIA is set up to interrupt after 8 bits have been shifted into the shift register ;; The VIA is set up to interrupt after 8 bits have been shifted into the shift register
;; from the external clock pulses of the keyboard (additional hardware required to ;; from the external clock pulses of the keyboard (additional hardware required to
;; address the hardware bug of the VIA, where bit get lost when the external clock ;; address the hardware bug of the VIA, where bit get lost when the external clock
@ -16,8 +16,136 @@ INCLUDE_KEYBOARD = 1
.include "system.h65" .include "system.h65"
.scope kb .scope kb
Import kb,init,irq_shift_reg_handler,irq_timer_handler,keycode,key_read Import kb,init,irq_shift_reg_handler,irq_timer_handler,scancode,key_read
Import kb, CHARS_NOMOD, CHARS_MODSHIFT
ImportZp kb,status
KB_IO = IO1 KB_IO = IO1
.enum STATUS
RELEASE = %10000000
TWOBYTE = %01000000
SHIFT = %00100000
CAPSLOCK = %00010000
CAPSLOCK_HELD = %00000010
RIGHTALT = %00001000
NUMLOCK = %00000100
.endenum
K_TWOBYTE = $E0
K_RELEASE = $F0
.enum K
F9 = $01
F5 = $03
F3 = $04
F1 = $05
F2 = $06
F12 = $07
F10 = $09
F8 = $0A
F6 = $0B
F4 = $0C
TAB = $0D
GRAVE = $0E
LEFTALT = $11
LEFTSHIFT = $12
LEFTCTRL = $14
K_Q = $15
K_1 = $16
K_Y = $1A
K_S = $1B
K_A = $1C
K_W = $1D
K_2 = $1E
K_C = $21
K_X = $22
K_D = $23
K_E = $24
K_4 = $25
K_3 = $26
SPACE = $29
K_V = $2A
K_F = $2B
K_T = $2C
K_R = $2D
K_5 = $2E
K_N = $31
K_B = $32
K_H = $33
K_G = $34
K_Z = $35
K_6 = $36
K_M = $3A
K_J = $3B
K_U = $3C
K_7 = $3D
K_8 = $3E
COMMA = $41
K_K = $42
K_I = $43
K_O = $44
K_0 = $45
K_9 = $46
DOT = $49
DASH = $4A
K_L = $4B
OUML = $4C
K_P = $4D
SSHARP = $4E
AUML = $52
UUML = $54
BACKTICK = $55
CAPSLOCK = $58
RIGHTSHIFT = $59
ENTER = $5A
PLUS = $5B
HASH = $5D
LESSTHAN = $61
BACKSPACE = $66
KP1 = $69
KP4 = $6B
KP7 = $6C
KP0 = $70
KPDOT = $71
KP2 = $72
KP5 = $73
KP6 = $74
KP8 = $75
ESCAPE = $76
NUMLOCK = $77
F11 = $78
KPPLUS = $79
KP3 = $7A
KPMINUS = $7B
KPASTERISK = $7C
KP9 = $7D
SCROLLLOCK = $7E
F7 = $83
.endenum
.enum K2
RIGHTALT = $11
RIGHTCTRL = $14
LEFTMETA = $1F
RIGHTMETA = $27
MENU = $2F
BREAK = $37
SYSRQ = $3F
KPDIVIDE = $4A
KPENTER = $5A
END = $69
LEFT = $6B
POS1 = $6C
INSERT = $70
DELETE = $71
DOWN = $72
RIGHT = $74
UP = $75
PAGEDOWN = $7A
PAGEUP = $7D
.endenum
.endscope .endscope
.endif
.endif ; guard

View File

@ -1,11 +1,15 @@
.include "keyboard.h65" .include "keyboard.h65"
.include "string.h65" .include "string.h65"
.include "lcd.h65" .include "lcd.h65"
Export kb,init,irq_shift_reg_handler,irq_timer_handler,keycode,key_read Export kb,init,irq_shift_reg_handler,irq_timer_handler,scancode,key_read
Export kb, CHARS_NOMOD, CHARS_MODSHIFT
ExportZp kb,status
.zeropage
status:
.bss .bss
key_read: .res 2 key_read: .res 2
keycode: .res 1 scancode: .res 1
.code .code
;;******************************************************************************** ;;********************************************************************************
@ -25,6 +29,8 @@ keycode: .res 1
sta kb::KB_IO + IO::T2CL sta kb::KB_IO + IO::T2CL
stz key_read stz key_read
stz key_read+1 stz key_read+1
stz scancode
stz status
; enable SR interrupts ; enable SR interrupts
lda #(IO::IRQ::IRQ | IO::IRQ::SR) lda #(IO::IRQ::IRQ | IO::IRQ::SR)
@ -60,7 +66,7 @@ keycode: .res 1
lda #(IO::IRQ::IRQ | IO::IRQ::T2) lda #(IO::IRQ::IRQ | IO::IRQ::T2)
sta kb::KB_IO + IO::IER sta kb::KB_IO + IO::IER
; start timer, low order count already in latch after init ; start timer, low order count already in latch after init
lda #1 lda #0
sta kb::KB_IO + IO::T2CH sta kb::KB_IO + IO::T2CH
rts rts
.endproc .endproc
@ -84,23 +90,49 @@ keycode: .res 1
; disable timer interrupts ; disable timer interrupts
lda #(IO::IRQ::T2) lda #(IO::IRQ::T2)
sta kb::KB_IO + IO::IER sta kb::KB_IO + IO::IER
; reset SR
; disabling shifting in acr seems necessary to reset - otherwise
; it continues counting and interrupts after the first 5 bits of the next keypress
lda #(IO::ACR::SR_SIN_PHIE | IO::ACR::T2_IRQ_LOAD)
trb kb::KB_IO + IO::ACR
tsb kb::KB_IO + IO::ACR
stz kb::KB_IO + IO::SR
; enable shift register interrupts ; enable shift register interrupts
lda #(IO::IRQ::IRQ | IO::IRQ::SR) lda #(IO::IRQ::IRQ | IO::IRQ::SR)
sta kb::KB_IO + IO::IER sta kb::KB_IO + IO::IER
; reset SR
stz kb::KB_IO + IO::SR
; rotate bit 2 (last bit of keycode) into the carry
lda key_read+1 lda key_read+1
ror ror
ror ror
ror ror
lda key_read ; not affecting carry lda key_read ; not affecting carry
rol ; rotate carry into byte, rotate startbit into carry rol ; rotate carry into byte, rotate startbit into carry
; TODO byte is inverted, maybe consider wasting 256 bytes for a bit reverse lookup table? Reverse A
sta keycode sta scancode
stz key_read
stz key_read+1
rts rts
.endproc .endproc
.rodata
.align 256
CHARS_NOMOD:
.byte "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x00"
.byte "\x00\x00\x00\x00\x00q1\x00\x00\x00ysaw2\x00"
.byte "\x00cxde43\x00\x00 vftr5\x00"
.byte "\x00nbhgz6\x00\x00\x00mju78\x00"
.byte "\x00,kio09\x00\x00.-l\xEFp\xE2\x00"
.byte "\x00\x00\xE1\x00\xF5`\x00\x00\x00\x00\x00\x00\x00#\x00\x00"
.byte "\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
.byte "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
.align 256
CHARS_MODSHIFT:
.byte "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xDF\x00"
.byte "\x00\x00\x00\x00\x00Q!\x00\x00\x00YSAW\"\x00"
.byte "\x00CXDE$\xED\x00\x00 VFTR%\x00"
.byte "\x00NBHGZ&\x00\x00\x00MJU/(\x00"
.byte "\x00;KIO=)\x00\x00:_L\xEFP\xE2\x00"
.byte "\x00\x00\xE1\x00\xF5`\x00\x00\x00\x00\x00\x00\x00'\x00\x00"
.byte "\x00>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
.byte "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"

View File

@ -22,9 +22,9 @@ charcount: .res 1
lda #$ff ; RB 0-7 output lda #$ff ; RB 0-7 output
sta lcd::LCD_IO+IO::DDRB sta lcd::LCD_IO+IO::DDRB
MaskedWrite lcd::LCD_IO+IO::DDRA, #(lcd::RS | lcd::RW | lcd::E), #lcd::RA_MASK lda lcd::LCD_IO+IO::DDRA
; lda #(lcd::RS | lcd::RW | lcd::E) ; RA 5-7 output ora #(lcd::RS | lcd::RW | lcd::E)
; sta lcd::LCD_IO+IO::DDRA sta lcd::LCD_IO+IO::DDRA
; init lcd ; init lcd
lda #lcd::CMD_FUNCTION_SET lda #lcd::CMD_FUNCTION_SET
@ -176,19 +176,24 @@ charcount: .res 1
.proc _wait_nbusy .proc _wait_nbusy
pha pha
stz lcd::LCD_IO + IO::DDRB ; set IO1-IO + IO::RB to input stz lcd::LCD_IO + IO::DDRB ; set IO1-IO + IO::RB to input
@lcd_wait_nbusy_loop: ; read the busy flag lda lcd::LCD_IO + IO::RA
; TODO use update_with_mask and #<~lcd::RA_MASK
lda #lcd::RW ora #lcd::RW
sta lcd::LCD_IO + IO::RA sta lcd::LCD_IO + IO::RA
lda #(lcd::RW | lcd::E)
@lcd_wait_nbusy_loop: ; read the busy flag
; set E low, then high
lda lcd::LCD_IO + IO::RA
and #<~lcd::E
sta lcd::LCD_IO + IO::RA
ora #lcd::E
sta lcd::LCD_IO + IO::RA sta lcd::LCD_IO + IO::RA
lda lcd::LCD_IO + IO::RB lda lcd::LCD_IO + IO::RB
bmi @lcd_wait_nbusy_loop ; msb set bmi @lcd_wait_nbusy_loop ; msb set
; and #%10000000 ; and updates zero flag, if not set retry
; bne @lcd_wait_nbusy_loop
lda #%00000000 ; TODO dont overwrite 0-4 lda lcd::LCD_IO + IO::RA
and #<~lcd::RA_MASK
sta lcd::LCD_IO + IO::RA sta lcd::LCD_IO + IO::RA
lda #%11111111 ; set IO1-IO + IO::RB to output lda #%11111111 ; set IO1-IO + IO::RB to output
sta lcd::LCD_IO + IO::DDRB sta lcd::LCD_IO + IO::DDRB

View File

@ -12,16 +12,17 @@ INCLUDE_SPI = 1
.scope spi_p .scope spi_p
SPI_IO = IO2 SPI_IO = IO2
Import spi_p, irq_handler, end, status Import spi_p, init, irq_handler, status, buffer_size, recv_size
Import spi_p, begin_read, irq_read_byte, recv_bytes ImportZp spi_p, buffer_ptr
Import spi_p, begin_write, irq_write_byte, sent_bytes Import spi_p, begin_read, end_read, irq_read_byte, recv_bytes
Import spi_p, begin_write, end_write, irq_write_byte, sent_bytes
.enum STATUS .enum STATUS
XFER_SIZEL = %10000000 XFER_SIZEL = %10000000
XFER_SIZEH = %01000000 XFER_SIZEH = %01000000
XFER = %00000001 XFER = %00000001
DONE = %00000000 DONE = %00000000
ERROR = %11111111 ERROR = %00100000
.endenum .endenum
.endscope .endscope

View File

@ -1,17 +1,20 @@
.include "spi.h65" .include "spi.h65"
.include "system.h65" .include "system.h65"
Export spi_p, irq_handler, end, status Export spi_p, init, irq_handler, status, buffer_size, recv_size
Export spi_p, begin_read, irq_read_byte, recv_bytes ExportZp spi_p, buffer_ptr
Export spi_p, begin_write, irq_write_byte, sent_bytes Export spi_p, begin_read, end_read, irq_read_byte, recv_bytes
Export spi_p, begin_write, end_write, irq_write_byte, sent_bytes
.zeropage .zeropage
buffer_start: .res 2 buffer_ptr: .res 2
.bss .bss
recv_bytes: recv_bytes:
sent_bytes: .res 2 sent_bytes: .res 2
status: .res 1 status: .res 1
buffer_size: .res 2 buffer_size: .res 2
recv_size:
send_size: .res 2
irq_handler: .res 2 irq_handler: .res 2
@ -27,6 +30,13 @@ SPI_IO := spi_p::SPI_IO
.proc init .proc init
lda #spi_p::STATUS::DONE lda #spi_p::STATUS::DONE
sta status sta status
stz recv_bytes
stz recv_bytes+1
stz buffer_size
stz buffer_size+1
stz recv_size
stz recv_size+1
rts
.endproc .endproc
@ -46,14 +56,16 @@ SPI_IO := spi_p::SPI_IO
.proc begin_read .proc begin_read
stz recv_bytes stz recv_bytes
stz recv_bytes+1 stz recv_bytes+1
stz recv_size
stz recv_size+1
lda #spi_p::STATUS::XFER_SIZEL lda #spi_p::STATUS::XFER_SIZEL
sta status sta status
; store address in zp ; store address in zp
lda #<ARG0 lda ARG0
sta buffer_start sta buffer_ptr
lda #>ARG1 lda ARG1
sta buffer_start+1 sta buffer_ptr+1
; load irq handler ; load irq handler
lda #<irq_read_byte lda #<irq_read_byte
@ -62,9 +74,9 @@ SPI_IO := spi_p::SPI_IO
sta irq_handler+1 sta irq_handler+1
; temporarily store the low byte in buffer, will be checked later ; temporarily store the low byte in buffer, will be checked later
lda #<ARG2 lda ARG2
sta (buffer_start) sta buffer_size
lda #>ARG3 lda ARG3
sta buffer_size+1 sta buffer_size+1
; set Shift register to shift in under external clock on CB1 ; set Shift register to shift in under external clock on CB1
MaskedWrite SPI_IO+IO::ACR, #IO::ACR::SR_SIN_PHIE, #IO::ACR_MASK::SR MaskedWrite SPI_IO+IO::ACR, #IO::ACR::SR_SIN_PHIE, #IO::ACR_MASK::SR
@ -83,10 +95,13 @@ SPI_IO := spi_p::SPI_IO
;; Disables shift register interrupts ;; Disables shift register interrupts
;; @modifies A ;; @modifies A
;;******************************************************************************** ;;********************************************************************************
.proc end end_write:
.proc end_read
; disable SR interrupts ; disable SR interrupts
lda #IO::IRQ::SR lda #IO::IRQ::SR
sta SPI_IO + IO::IER sta SPI_IO + IO::IER
lda #spi_p::STATUS::DONE
sta status
rts rts
.endproc .endproc
@ -104,35 +119,36 @@ SPI_IO := spi_p::SPI_IO
;;******************************************************************************** ;;********************************************************************************
.proc irq_read_byte .proc irq_read_byte
lda SPI_IO + IO::SR lda SPI_IO + IO::SR
; Printf "%x",
bit status bit status
bmi @read_size1 bmi @read_size1 ; bit7 set => XFER_SIZEL
bvs @read_size2 bvs @read_size2 ; bit6 set => XFER_SIZEH
ldy recv_bytes ldy recv_bytes
sta (buffer_start),y sta (buffer_ptr),y
inc recv_bytes inc recv_bytes
beq @new_page beq @new_page
rts rts
@new_page: @new_page: ; increment high bytes
inc recv_bytes+1 inc recv_bytes+1
inc buffer_start+1 inc buffer_ptr+1
rts rts
@read_size1: @read_size1:
sta buffer_size sta recv_size
lda #spi_p::STATUS::XFER_SIZEH lda #spi_p::STATUS::XFER_SIZEH
sta status sta status
rts rts
@read_size2: @read_size2:
; todo: check if the buffer is large enough: sta recv_size+1
; low byte of buffer size in (buffer_start), high byte in buffer_size+1 ; check if the buffer is large enough
; low byte of recv buffer size in buffer_size, high byte in A
cmp buffer_size+1 cmp buffer_size+1
beq @hieq beq @hieq
sta buffer_size+1 bcc @enough ; recv_size+1 < buffer_size+1
bcs @enough ; buffer larger
bra @not_enough bra @not_enough
@hieq: ; high bytes are equal, check lo @hieq: ; high bytes are equal, check lo
lda (buffer_start) lda buffer_size
cmp buffer_size cmp recv_size
bcs @enough bcs @enough
@not_enough: @not_enough:
lda #spi_p::STATUS::ERROR lda #spi_p::STATUS::ERROR
@ -163,9 +179,9 @@ SPI_IO := spi_p::SPI_IO
stz recv_bytes+1 stz recv_bytes+1
; store address in zp ; store address in zp
lda #<ARG0 lda #<ARG0
sta buffer_start sta buffer_ptr
lda #>ARG1 lda #>ARG1
sta buffer_start+1 sta buffer_ptr+1
; store size ; store size
lda #<ARG2 lda #<ARG2
sta buffer_size sta buffer_size
@ -188,7 +204,6 @@ SPI_IO := spi_p::SPI_IO
lda #spi_p::STATUS::XFER_SIZEH lda #spi_p::STATUS::XFER_SIZEH
sta status sta status
rts rts
rts
.endproc .endproc
;;;******************************************************************************** ;;;********************************************************************************
@ -199,14 +214,14 @@ SPI_IO := spi_p::SPI_IO
;;;******************************************************************************** ;;;********************************************************************************
;.proc irq_write_byte ;.proc irq_write_byte
; ldy sent_bytes ; ldy sent_bytes
; lda (buffer_start),y ; lda (buffer_ptr),y
; sta SPI_IO + IO::SR ; sta SPI_IO + IO::SR
; inc sent_bytes ; inc sent_bytes
; beq @new_page ; beq @new_page
; rts ; rts
;@new_page: ;@new_page:
; inc sent_bytes+1 ; inc sent_bytes+1
; inc buffer_start+1 ; inc buffer_ptr+1
; rts ; rts
;.endproc ;.endproc
@ -223,14 +238,14 @@ SPI_IO := spi_p::SPI_IO
bit status bit status
bvs @write_size2 ; bit 6 set -> XFER_SIZEH bvs @write_size2 ; bit 6 set -> XFER_SIZEH
ldy sent_bytes ldy sent_bytes
lda (buffer_start),y lda (buffer_ptr),y
sta SPI_IO + IO::SR sta SPI_IO + IO::SR
inc sent_bytes inc sent_bytes
beq @new_page beq @new_page
rts rts
@new_page: @new_page:
inc sent_bytes+1 inc sent_bytes+1
inc buffer_start+1 inc buffer_ptr+1
rts rts
@write_size2: @write_size2:
lda buffer_size+1 lda buffer_size+1
@ -239,4 +254,3 @@ SPI_IO := spi_p::SPI_IO
sta status sta status
rts rts
.endproc .endproc

View File

@ -67,4 +67,13 @@ IO1 = $6000
; IO2: .res 16 ; IO2: .res 16
IO2 = $7000 IO2 = $7000
; charmappings for the lcd
; .charmap 'ü', $F5
; .charmap 'Ü', $F5
; .charmap 'ö', $EF
; .charmap 'Ö', $EF
; .charmap 'ä', $E1
; .charmap 'Ä', $E1
; .charmap 'ß', $E2
.endif ; include guard .endif ; include guard

View File

@ -1,8 +1,23 @@
.include "system/system.h65" .include "system/system.h65"
.include "system/lcd.h65"
.segment "TEST" .segment "TEST"
.macro MaskedWrite2 addr,value,mask
lda #value
eor addr
and #mask
eor addr
sta addr
.endmacro
.import __SPI_SIZE__
label: label:
JsrIndirect $2022 ; JsrIndirect $2022
.byte 0,1,2,3,4 ; .byte 0,1,2,3,4
JsrIndirect {($2022,x)}, label ; JsrIndirect {($2022,x)}, label
.byte 5,6,7,8,9 ; .byte 5,6,7,8,9
; MaskedWrite2 lcd::LCD_IO+IO::DDRA, (lcd::RS | lcd::RW | lcd::E), lcd::RA_MASK
; lda #(lcd::RS | lcd::RW | lcd::E) ; RA 5-7 output
; sta lcd::LCD_IO+IO::DDRA
.word __SPI_SIZE__
.byte >__SPI_SIZE__
.byte <__SPI_SIZE__

38
util/reverse.s65 Normal file
View File

@ -0,0 +1,38 @@
.export REVERSE_TABLE
.rodata
.align 256
REVERSE_TABLE:
.byte $00, $80, $40, $c0, $20, $a0, $60, $e0
.byte $10, $90, $50, $d0, $30, $b0, $70, $f0
.byte $08, $88, $48, $c8, $28, $a8, $68, $e8
.byte $18, $98, $58, $d8, $38, $b8, $78, $f8
.byte $04, $84, $44, $c4, $24, $a4, $64, $e4
.byte $14, $94, $54, $d4, $34, $b4, $74, $f4
.byte $0c, $8c, $4c, $cc, $2c, $ac, $6c, $ec
.byte $1c, $9c, $5c, $dc, $3c, $bc, $7c, $fc
.byte $02, $82, $42, $c2, $22, $a2, $62, $e2
.byte $12, $92, $52, $d2, $32, $b2, $72, $f2
.byte $0a, $8a, $4a, $ca, $2a, $aa, $6a, $ea
.byte $1a, $9a, $5a, $da, $3a, $ba, $7a, $fa
.byte $06, $86, $46, $c6, $26, $a6, $66, $e6
.byte $16, $96, $56, $d6, $36, $b6, $76, $f6
.byte $0e, $8e, $4e, $ce, $2e, $ae, $6e, $ee
.byte $1e, $9e, $5e, $de, $3e, $be, $7e, $fe
.byte $01, $81, $41, $c1, $21, $a1, $61, $e1
.byte $11, $91, $51, $d1, $31, $b1, $71, $f1
.byte $09, $89, $49, $c9, $29, $a9, $69, $e9
.byte $19, $99, $59, $d9, $39, $b9, $79, $f9
.byte $05, $85, $45, $c5, $25, $a5, $65, $e5
.byte $15, $95, $55, $d5, $35, $b5, $75, $f5
.byte $0d, $8d, $4d, $cd, $2d, $ad, $6d, $ed
.byte $1d, $9d, $5d, $dd, $3d, $bd, $7d, $fd
.byte $03, $83, $43, $c3, $23, $a3, $63, $e3
.byte $13, $93, $53, $d3, $33, $b3, $73, $f3
.byte $0b, $8b, $4b, $cb, $2b, $ab, $6b, $eb
.byte $1b, $9b, $5b, $db, $3b, $bb, $7b, $fb
.byte $07, $87, $47, $c7, $27, $a7, $67, $e7
.byte $17, $97, $57, $d7, $37, $b7, $77, $f7
.byte $0f, $8f, $4f, $cf, $2f, $af, $6f, $ef
.byte $1f, $9f, $5f, $df, $3f, $bf, $7f, $ff

View File

@ -11,7 +11,7 @@ INCLUDE_STRING = 1
.scope str .scope str
Import str, strf Import str, strf, printf_buffer
Import str, hex_char_to_uint8, hex_str_to_uint Import str, hex_char_to_uint8, hex_str_to_uint
Import str, uint8_to_hex_str, uint_to_hex_str Import str, uint8_to_hex_str, uint_to_hex_str
@ -74,5 +74,10 @@ Import str, uint8_to_hex_str, uint_to_hex_str
; .out .sprintf("info: Strf: called with %d arguments", @N_ARGS) ; .out .sprintf("info: Strf: called with %d arguments", @N_ARGS)
.endmacro .endmacro
.macro Printf fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9
Strf fmt,str::printf_buffer,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9
PrintNC str::printf_buffer
.endmacro
.endscope .endscope
.endif ; guard .endif ; guard

View File

@ -1,5 +1,8 @@
.include "string.h65" .include "string.h65"
Export str, strf Export str, strf, printf_buffer
.bss
printf_buffer: .res $41
.zeropage .zeropage
fmt_idx: .res 1 fmt_idx: .res 1

View File

@ -7,6 +7,34 @@ INCLUDE_UTILITY = 1
.feature string_escapes .feature string_escapes
.feature underline_in_numbers .feature underline_in_numbers
.macro DEBUG_LED_OFF nr
pha
lda IO1 + IO::RA
.if nr = 0
and #%11111110
.elseif nr = 1
and #%11111101
.else
and #%11111011
.endif
sta IO1 + IO::RA
pla
.endmacro
.macro DEBUG_LED_ON nr
pha
lda IO1 + IO::RA
.if nr = 0
ora #%00000001
.elseif nr = 1
ora #%00000010
.else
ora #%00000100
.endif
sta IO1 + IO::RA
pla
.endmacro
;;******************************************************************************** ;;********************************************************************************
;; @macro Update a byte in memory using a mask ;; @macro Update a byte in memory using a mask
@ -17,6 +45,7 @@ INCLUDE_UTILITY = 1
;; xor #value with addr -> only bits that need to flip are 1 ;; xor #value with addr -> only bits that need to flip are 1
;; and result with #mask -> only selected bits that need to flip stay 1 ;; and result with #mask -> only selected bits that need to flip stay 1
;; xor result with addr -> flips selected bits ;; xor result with addr -> flips selected bits
;; @TODO optimize when immediate is used
;;******************************************************************************** ;;********************************************************************************
.macro MaskedWrite addr,value,mask .macro MaskedWrite addr,value,mask
lda value lda value
@ -123,4 +152,26 @@ _n_genlabel .set 0
.ident(.sprintf("%s", .string(l1))) = .ident(.sprintf("%s_%s", .string(prefix), .string(l1))) .ident(.sprintf("%s", .string(l1))) = .ident(.sprintf("%s_%s", .string(prefix), .string(l1)))
ImportZp prefix,l2,l3,l4,l5,l6,l7,l8 ImportZp prefix,l2,l3,l4,l5,l6,l7,l8
.endmacro .endmacro
.endif
.import REVERSE_TABLE
;;********************************************************************************
;; @macro Reverse a byte
;; @param reg: The byte to reverse. May be in X, Y or A
;; @returns A: The reversed byte
;; @modifies A, X (only when reg = A)
;;********************************************************************************
.macro Reverse reg
.if .match(reg, A)
tax
lda REVERSE_TABLE,x
.elseif .match(reg, x)
lda REVERSE_TABLE,x
.elseif .match(reg, y)
lda REVERSE_TABLE,y
.else
.fatal ("Reverse macro got invalid argument. This syntax error is intentional to show the line number")
.endif
.endmacro
.endif ; guard