Compare commits

..

No commits in common. "302e49a9f79f8e2255b6227e7c3bf23c7f924c19" and "25d0fcfb9016f60523f89c2d2dad4a39df60088c" have entirely different histories.

18 changed files with 201 additions and 542 deletions

View File

@ -7,7 +7,6 @@ MEMORY {
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;
TEST: start = $9000, size = $1000, type = rw, file = "../test.bin";
} }
SEGMENTS { SEGMENTS {
VIA1: load = VIA1, type = bss; VIA1: load = VIA1, type = bss;
@ -17,6 +16,5 @@ SEGMENTS {
CODE: load = ROM, type = ro; CODE: load = ROM, type = ro;
RODATA: load = ROM, type = ro; RODATA: load = ROM, type = ro;
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;
} }

View File

@ -65,7 +65,7 @@ irq:
@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
@irq_io2: @irq_io2:
@ -74,7 +74,6 @@ irq:
bbr7 irq_via_ifr,@irq_return ; skip bbr7 irq_via_ifr,@irq_return ; skip
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
; this SHOULD never be reached ; this SHOULD never be reached
jsr lcd::clear jsr lcd::clear
Print "Unknown IRQ" Print "Unknown IRQ"
@ -82,18 +81,23 @@ irq:
lda #$ff lda #$ff
sta IO1 + IO::IFR sta IO1 + IO::IFR
sta IO2 + IO::IFR sta IO2 + IO::IFR
bra @irq_return rti
; bra @irq_return
@irq_keypad: @irq_keypad:
jsr kp::read_irq lda #<@irq_return
bra @irq_return pha
lda #>@irq_return
pha
jmp (spi_p::irq_handler)
@irq_spi_p: @irq_spi_p:
JsrIndirect (spi_p::irq_handler), @irq_return jsr spi_p::read
bra @irq_return
@irq_kb1: @irq_kb1:
Print "$3000" ; PrintNC "<30>"
jsr $3000 jsr $3000
bra @irq_return bra @irq_return
@irq_kb2: @irq_kb2:
Print "$3100" ; PrintNC "<31>"
jsr $3100 jsr $3100
bra @irq_return bra @irq_return
; @irq_dht: ; @irq_dht:

View File

@ -3,16 +3,15 @@ INCLUDE_MEMCOPY = 1
.include "system.h65" .include "system.h65"
.export memcopy,memcopy16 .export memcopy
.code .code
;;******************************************************************************** ;********************************************************************************
;; @function Copy a block of memory to a different address ; @function Copy a block of memory to a different address
;; @param ARG0-1: Source address ; @param ARG0-1: Source address
;; @param ARG2-3: Target address ; @param ARG2-3: Target address
;; @param Y: Number of bytes to copy ; @param y: Number of bytes to copy
;; @modifies: A,Y ;********************************************************************************
;;********************************************************************************
.proc memcopy .proc memcopy
cpy #0 cpy #0
beq @rts beq @rts
@ -25,41 +24,5 @@ INCLUDE_MEMCOPY = 1
@rts: @rts:
rts rts
.endproc .endproc
;;********************************************************************************
;; @function Copy a block of memory to a different address
;; @param ARG0-1: Source address
;; @param ARG2-3: Target address
;; @param ARG5-6: Number of bytes to copy (LE)
;; @modifies: A,Y
;;********************************************************************************
.proc memcopy16
lda ARG6
beq @last_page ; no full page
ldy #$ff
bra @copy_byte
@next_page: ; y is 0
lda ARG6
beq @rts ; done
inc ARG1
inc ARG3
dec ARG6
beq @last_page
ldy #$ff
@copy_byte:
lda (ARG0),y
sta (ARG2),y
@dec_y:
dey
beq @next_page
bra @copy_byte
@last_page:
ldy ARG5
dey
bra @copy_byte
@rts:
rts
.endproc
.endif ; guard .endif ; guard

View File

@ -4,56 +4,43 @@
.include "lcd.h65" .include "lcd.h65"
.include "chars.h65" .include "chars.h65"
.import home:absolute .import home:absolute
.import CODE_START: absolute .import SPI_IO
.import __SPI_SIZE__
.export spi_menu .export spi_menu
.bss .bss
trans_bytes: .res 2 ; used to check if screen needs to be updated trans_bytes: .res 1
status_char: .res 1 trans_pages: .res 1
status: .res 1
status_str: .res 17 ; 16 + null status_str: .res 17 ; 16 + null
.code .code
.proc spi_menu .proc spi_menu
stz trans_bytes stz trans_bytes
stz trans_bytes+1 stz trans_pages
lda #'X'
sta status
@print_menu: @print_menu:
jsr lcd::clear jsr lcd::clear
Print MENU Print MENU
@update_status:
lda spi_p::status
cmp #spi_p::STATUS::ERROR
beq @status_ERROR
cmp #spi_p::STATUS::DONE
beq @status_DONE
bra @status_XFER
@status_ERROR:
lda #'E'
bra @update_status_end
@status_DONE:
lda #'O'
bra @update_status_end
@status_XFER:
lda #'X'
@update_status_end:
sta status_char
@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 FMT_STATUS,status_str,trans_pages,trans_bytes,status
PrintNC status_str PrintNC status_str
@loop: @loop:
; check if a byte has been transferred ; check if a byte has been transferred
@check_received: @check_byte:
lda spi_p::recv_bytes lda spi_p::bytes_written
cmp trans_bytes cmp trans_bytes
beq @read_keypad beq @read_keypad
@byte_received: @byte_written:
sta trans_bytes sta trans_bytes
lda spi_p::recv_bytes+1 @check_page:
lda trans_bytes+1 lda spi_p::pages_written
cmp trans_pages
beq @read_keypad
@page_written:
sta trans_pages
bra @print_status bra @print_status
@read_keypad: @read_keypad:
lda kp::_DEBUG_VAL lda kp::_DEBUG_VAL
@ -70,26 +57,22 @@ 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 bra @loop
@spi_begin: @spi_begin:
lda #<CODE_START lda #'@'
sta ARG0 sta status
lda #>CODE_START jsr spi_p::begin
sta ARG1
lda #<__SPI_SIZE__
sta ARG2
lda #>__SPI_SIZE__
sta ARG3
jsr spi_p::begin_read
jmp @print_menu jmp @print_menu
@spi_end: @spi_end:
lda #'X'
sta status
jsr spi_p::end jsr spi_p::end
jmp @print_menu jmp @print_menu
@spi_jump: @spi_jump:
jsr spi_p::end jsr spi_p::end
jsr lcd::clear jsr lcd::clear
Print START Print START
jmp CODE_START jmp spi_p::CODE_START
@return_home: @return_home:
jsr spi_p::end jsr spi_p::end
jmp home jmp home

View File

@ -3,7 +3,6 @@
.include "lcd.h65" .include "lcd.h65"
.include "math.h65" .include "math.h65"
.include "keypad.h65" .include "keypad.h65"
.include "keyboard.h65"
.include "chars.h65" .include "chars.h65"
.import homeloop:absolute .import homeloop:absolute
.import home:absolute .import home:absolute
@ -13,6 +12,9 @@
.import memcopy .import memcopy
.scope kb
KB_IO = IO1
.endscope
CODE_START: CODE_START:
@ -58,7 +60,7 @@ CODE_START:
; PrintNC $3000 ; PrintNC $3000
jsr kb::init jsr kbinit
lda #'%' lda #'%'
jsr lcd::print_char jsr lcd::print_char
@ -108,7 +110,7 @@ CODE_START:
jsr lcd::print_char jsr lcd::print_char
bra @loop bra @loop
@lB: @lB:
Strf fmt_str, out_str, kb::keycode Strf fmt_str, out_str, keycode
Print out_str Print out_str
bra @loop bra @loop
@lC: @lC:
@ -166,11 +168,11 @@ CODE_START:
; .endproc ; .endproc
.proc irq_timer_handler .proc irq_on_timer
; lda #'<' ; lda #'<'
; jsr lcd::print_char ; jsr lcd::print_char
lda kb::KB_IO + IO::SR lda kb::KB_IO + IO::SR
sta kb::key_read + 1 sta key_read + 1
lda kb::KB_IO + IO::T2CL ; clear interrupt flag lda kb::KB_IO + IO::T2CL ; clear interrupt flag
@ -188,16 +190,16 @@ CODE_START:
ror ror
ror ror
ror ror
lda kb::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? ; TODO byte is inverted, maybe consider wasting 256 bytes for a bit reverse lookup table?
sta kb::keycode sta keycode
Strf fmt_str2, out_str, kb::keycode, kb::key_read, kb::key_read+1 Strf fmt_str2, out_str, keycode, key_read, key_read+1
PrintNC out_str PrintNC out_str
stz kb::key_read stz key_read
stz kb::key_read+1 stz key_read+1
rts rts
.endproc .endproc
@ -207,7 +209,7 @@ CODE_START:
kb_irq1: kb_irq1:
; lda #'!' ; lda #'!'
; jsr lcd::print_char ; jsr lcd::print_char
jsr kb::irq_shift_reg_handler jsr kb::on_shift_reg_irq
; lda #':' ; lda #':'
; jsr lcd::print_char ; jsr lcd::print_char
rts rts
@ -216,7 +218,7 @@ 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 irq_on_timer
; lda #';' ; lda #';'
; jsr lcd::print_char ; jsr lcd::print_char
rts rts

View File

@ -1,7 +1,7 @@
;;******************************************************************************** ;********************************************************************************
;; @module irq_handler ; @module irq_handler
;; @type system ; @type system
;;******************************************************************************** ;********************************************************************************
.ifndef INCLUDE_IRQ_HANDLER .ifndef INCLUDE_IRQ_HANDLER
INCLUDE_IRQ_HANDLER = 1 INCLUDE_IRQ_HANDLER = 1

View File

@ -1,23 +0,0 @@
;;********************************************************************************
;; @module keyboard
;; @type drive
;; @details:
;; 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
;; 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
;; address the hardware bug of the VIA, where bit get lost when the external clock
;; transition happens during falling edge of PHI2). After reading the shift register,
;; the VIAs T2 timer is set to interrupt after the last 3 bits have been shifted in,
;; which takes about ~230ms.
;;********************************************************************************
.ifndef INCLUDE_KEYBOARD
INCLUDE_KEYBOARD = 1
.include "system.h65"
.scope kb
Import kb,init,irq_shift_reg_handler,irq_timer_handler,keycode,key_read
KB_IO = IO1
.endscope
.endif

View File

@ -1,106 +0,0 @@
.include "keyboard.h65"
.include "string.h65"
.include "lcd.h65"
Export kb,init,irq_shift_reg_handler,irq_timer_handler,keycode,key_read
.bss
key_read: .res 2
keycode: .res 1
.code
;;********************************************************************************
;; @function Initialize the PS2 keyboard
;; @modifies: A
;;********************************************************************************
.proc init
; - 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
; (this could be shorter since the it takes a few cycles after the interrupt)
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
rts
.endproc
;;********************************************************************************
;; @function Read the first 8 bits an
;; @modifies: A
;; @details
;; - read shift register
;; - disable shift register interrupts
;; - reset shift register
;; - enable timer 2 interrupts
;; - start timer 2
;; IO::SR has to be read before the next bit is shifted in, which happens ~75us after the irq
;; at 1MHz, handling this interrupt takes about 50us (without any additional debug code),
;; so it should work
;;********************************************************************************
.proc irq_shift_reg_handler
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, low order count already in latch after init
lda #1
sta kb::KB_IO + IO::T2CH
rts
.endproc
;;********************************************************************************
;; @function Read the last 3 bits after after timer 2 is up
;; @modifies: A
;; @details
;; - read shift register
;; - disable timer 2 interrupts
;; - enable shift register interrupts
;; - reset shift register
;;********************************************************************************
.proc irq_timer_handler
lda kb::KB_IO + IO::SR
sta 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
; rotate bit 2 (last bit of keycode) into the carry
lda key_read+1
ror
ror
ror
lda 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 keycode
stz key_read
stz key_read+1
rts
.endproc

View File

@ -22,7 +22,7 @@ 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 MaskedWrite 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 ; lda #(lcd::RS | lcd::RW | lcd::E) ; RA 5-7 output
; sta lcd::LCD_IO+IO::DDRA ; sta lcd::LCD_IO+IO::DDRA

View File

@ -12,9 +12,7 @@ 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, begin_read, irq_read_byte, begin_write, irq_write_byte, end, recv_bytes, sent_bytes, status
Import spi_p, begin_read, irq_read_byte, recv_bytes
Import spi_p, begin_write, irq_write_byte, sent_bytes
.enum STATUS .enum STATUS
XFER_SIZEL = %10000000 XFER_SIZEL = %10000000
@ -26,17 +24,3 @@ Import spi_p, begin_write, irq_write_byte, sent_bytes
.endscope .endscope
.endif ; guard .endif ; guard
; .struct SPI_P_Pins
; ; VIA addresses
; DDR_a .word ; address of the data direction register
; R_a .word ; address of the register
; ; pin mask
; SCLK_p .byte ; Serial Clock
; POCI_p .byte ; Peripheral Out / Controller In
; PICO_p .byte ; Peripheral In / Controller Out
; CSB_p .byte ; Chip Select
; ; settings
; CPOL .byte ; Clock Polarity
; CPHA .byte ; Clock Phase
; .endstruct

View File

@ -1,9 +1,6 @@
.include "spi.h65" .include "spi.h65"
.include "system.h65"
Export spi_p, irq_handler, end, status Export spi_p, begin_read, irq_read_byte, begin_write, irq_write_byte, end, recv_bytes, sent_bytes, status, spi_irq
Export spi_p, begin_read, irq_read_byte, recv_bytes
Export spi_p, begin_write, irq_write_byte, sent_bytes
.zeropage .zeropage
buffer_start: .res 2 buffer_start: .res 2
@ -20,14 +17,19 @@ SPI_IO := spi_p::SPI_IO
; spi-transferred code will be placed here ; spi-transferred code will be placed here
; SPI_P = as peripheral ; SPI_P = as peripheral
.code .code
; .struct SPI_P_Pins
;;******************************************************************************** ; ; VIA addresses
;; @function Begin listening for SPI transfers ; DDR_a .word ; address of the data direction register
;;******************************************************************************** ; R_a .word ; address of the register
.proc init ; ; pin mask
lda #spi_p::STATUS::DONE ; SCLK_p .byte ; Serial Clock
sta status ; POCI_p .byte ; Peripheral Out / Controller In
.endproc ; PICO_p .byte ; Peripheral In / Controller Out
; CSB_p .byte ; Chip Select
; ; settings
; CPOL .byte ; Clock Polarity
; CPHA .byte ; Clock Phase
; .endstruct
;;******************************************************************************** ;;********************************************************************************
@ -46,7 +48,7 @@ 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
lda #spi_p::STATUS::XFER_SIZEL lda #%spi_p::STATUS::XFER_SIZEL
sta status sta status
; store address in zp ; store address in zp
@ -184,7 +186,7 @@ SPI_IO := spi_p::SPI_IO
; write the first byte ; write the first byte
@write_size1: @write_size1:
lda buffer_size lda buffer_size
sta SPI_IO+IO::SR sta SPI_IO+IO_SR
lda #spi_p::STATUS::XFER_SIZEH lda #spi_p::STATUS::XFER_SIZEH
sta status sta status
rts rts
@ -234,9 +236,11 @@ SPI_IO := spi_p::SPI_IO
rts rts
@write_size2: @write_size2:
lda buffer_size+1 lda buffer_size+1
sta SPI_IO+IO::SR sta SPI_IO+IO_SR
lda #spi_p::STATUS::XFER lda #spi_p::STATUS::XFER
sta status sta status
rts rts
.endproc .endproc
.endproc

View File

@ -8,57 +8,43 @@
.ifndef INCLUDE_SYSTEM .ifndef INCLUDE_SYSTEM
INCLUDE_SYSTEM = 1 INCLUDE_SYSTEM = 1
; reserved RAM addresses ; reserved RAM addresses
; 00-0f - free use (Z0-Z15) ; 00-0f - free
; 10-1f - arguments / return values (ARG0-ARG15) ; 10-1f - arguments / return values
; 20-ff - free ; 20-ff - free
; 0100 - 01FF Stack ; 0100 - 01FF Stack
; 0200,0201 keybuffer write/read pointer ; 0200,0201 keybuffer write/read pointer
; 0202-02ff keybuffer ; 0202-02ff keybuffer
; 0300 lcd character counter ; 0300 lcd character counter
; 0400, 0401, 0402 dht status, dht bit, dht_bit_rot
; 0403 value offset
; 0405-04a0 rh high/low, temp high/low, checksum
.include "io_W65C22.h65" .include "io_W65C22.h65"
.include "utility.h65" .include "utility.h65"
.importzp Z0,Z1,Z2,Z3,Z4,Z5,Z6,Z7,Z8,Z9,Z10,Z11,Z12,Z13,Z14,Z15
.importzp ARG0,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8,ARG9,ARG10,ARG11,ARG12,ARG13,ARG14,ARG15
; Z0 = $0 ; ARGUMENTS
; Z1 = $1 ; a,x,y can also be used
; Z2 = $2 ARG0 = $10
; Z3 = $3 ARG1 = $11
; Z4 = $4 ARG2 = $12
; Z5 = $5 ARG3 = $13
; Z6 = $6 ARG4 = $14
; Z7 = $7 ARG5 = $15
; Z8 = $8 ARG6 = $16
; Z9 = $9 ARG7 = $17
; Z10 = $a ARG8 = $18
; Z11 = $b ARG9 = $19
; Z12 = $c ARG10 = $1a
; Z13 = $d ARG11 = $1b
; Z14 = $e ARG12 = $1c
; Z15 = $f ARG13 = $1d
; ; ARGUMENTS ARG14 = $1e
; ; a,x,y can also be used ARG15 = $1f
; ARG0 = $10
; ARG1 = $11
; ARG2 = $12
; ARG3 = $13
; ARG4 = $14
; ARG5 = $15
; ARG6 = $16
; ARG7 = $17
; ARG8 = $18
; ARG9 = $19
; ARG10 = $1a
; ARG11 = $1b
; ARG12 = $1c
; ARG13 = $1d
; ARG14 = $1e
; ARG15 = $1f
; RETURN VALUE ; RETURN VALUE
; in a
.segment "VIA1" .segment "VIA1"
; IO1: .res 16 ; IO1: .res 16
IO1 = $6000 IO1 = $6000

View File

@ -1,42 +1,3 @@
; .include "system.h65"
.exportzp Z0,Z1,Z2,Z3,Z4,Z5,Z6,Z7,Z8,Z9,Z10,Z11,Z12,Z13,Z14,Z15
.exportzp ARG0,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8,ARG9,ARG10,ARG11,ARG12,ARG13,ARG14,ARG15
.zeropage .zeropage
.org $0 .org $10
.assert * = $0, error, "Code not at 0" .res 16
Z0: .res 1
Z1: .res 1
Z2: .res 1
Z3: .res 1
Z4: .res 1
Z5: .res 1
Z6: .res 1
Z7: .res 1
Z8: .res 1
Z9: .res 1
Z10: .res 1
Z11: .res 1
Z12: .res 1
Z13: .res 1
Z14: .res 1
Z15: .res 1
; ARGUMENTS
; a,x,y can also be used
.assert * = $10, error, "Code not at 10"
ARG0: .res 1
ARG1: .res 1
ARG2: .res 1
ARG3: .res 1
ARG4: .res 1
ARG5: .res 1
ARG6: .res 1
ARG7: .res 1
ARG8: .res 1
ARG9: .res 1
ARG10: .res 1
ARG11: .res 1
ARG12: .res 1
ARG13: .res 1
ARG14: .res 1
ARG15: .res 1

View File

@ -1,8 +1,55 @@
.include "system/system.h65" ;.include "system/system.h65"
;.segment "CODE"
;;********************************************************************************
;; Interrupts
;;********************************************************************************
;nmi:
; rti
;irq:
; .repeat 20
; .endrepeat
; rti
;;********************************************************************************
;; Reset sequence
;;********************************************************************************
;reset:
; sei
; ; setup io2 bank a 1-3
; lda #%11111111
; sta IO1 + IO_DDRA
; sta IO1 + IO_DDRB
;@loop:
; lda #%00000000
; sta IO1 + IO_RA
; .repeat 3
; nop
; .endrepeat
; lda #%11111111
; sta IO1 + IO_RA
; .repeat 15
; nop
; .endrepeat
; lda #%00000000
; sta IO1 + IO_RB
; .repeat 5
; nop
; .endrepeat
; lda #%11111111
; sta IO1 + IO_RB
; .repeat 10
; nop
; .endrepeat
; bra @loop
;;********************************************************************************
;; reset vector
;;********************************************************************************
;.segment "RESET_VECTOR"
; .word nmi
; .word reset
; .word irq
.segment "TEST"
label:
JsrIndirect $2022
.byte 0,1,2,3,4
JsrIndirect {($2022,x)}, label
.byte 5,6,7,8,9

View File

@ -1,6 +1,6 @@
.include "string.h65" .include "string.h65"
.include "math.h65" .include "math.h65"
Export str,hex_char_to_uint8, hex_str_to_uint, uint8_to_hex_str, uint_to_hex_str Export str,hex_char_to_uint8, hex_str_to_uint, uint8_to_hex_str
.code .code
; ;
@ -130,55 +130,6 @@ Export str,hex_char_to_uint8, hex_str_to_uint, uint8_to_hex_str, uint_to_hex_str
.endproc .endproc
;;********************************************************************************
;; @function Convert a 1 byte number into two hex characters
;; @param A: Size of the number in bytes
;; @param X: Offset onto ARG4, so that the number starts at `ARG4+x` (BE)
;; @param ARG2-3: Pointer to output string
;; @param Y: Offset onto the string in ARG2-3
;; @returns A: 0
;; @returns X: Offset onto ARG4, past the end of the number
;; @returns Y: Offset onto the the string in ARG2-3, past the end of the number
;; @returns N: Clear if success, else set
;; @modifies A,X,Y
;;********************************************************************************
.proc uint_to_hex_str
@loop:
cmp #0
beq @rts
pha
lda ARG4,x
phx
pha
and #%00001111
tax
lda HEX_CHARS_UPPER,x
sta (ARG2),y
pla
iny
beq @overflow2
div A,16
and #%00001111
tax
lda HEX_CHARS_UPPER,x
sta (ARG2),y
iny
beq @overflow2
plx
pla
inx
beq @overflow
bra @loop
@overflow2:
plx
pla
@overflow:
lda #$ff ; set n
@rts:
rts
.endproc
.rodata .rodata
HEX_CHARS_UPPER: .byte "0123456789ABCDEF" HEX_CHARS_UPPER: .byte "0123456789ABCDEF"
HEX_CHARS_LOWER: .byte "0123456789abcdef" HEX_CHARS_LOWER: .byte "0123456789abcdef"

View File

@ -12,8 +12,7 @@ INCLUDE_STRING = 1
.scope str .scope str
Import str, strf Import str, strf
Import str, hex_char_to_uint8, hex_str_to_uint Import str, hex_char_to_uint8, hex_str_to_uint, uint8_to_hex_str
Import str, uint8_to_hex_str, uint_to_hex_str
.macro _StrfStoreArg arg .macro _StrfStoreArg arg
@ -36,7 +35,7 @@ Import str, uint8_to_hex_str, uint_to_hex_str
;; @param out: Output string address ;; @param out: Output string address
;; @param x0-x9: Additional parameters ;; @param x0-x9: Additional parameters
;; @warning Addresses as additional paramters must be passed like this `#<addr,#>addr` ;; @warning Addresses as additional paramters must be passed like this `#<addr,#>addr`
;; @modifies: A, X, Y, ARG4, ARG5 ;; @modifies: A, X, Y
;; @see strf ;; @see strf
;;******************************************************************************** ;;********************************************************************************
.macro Strf fmt,out,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9 .macro Strf fmt,out,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9
@ -74,5 +73,8 @@ 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
; TODO allocate zp memory
fmt_idx = $30
out_idx = $31
.endscope .endscope
.endif ; guard .endif ; guard

View File

@ -1,30 +1,24 @@
.include "string.h65" .include "string.h65"
Export str, strf Export str, strf
.zeropage
fmt_idx: .res 1
out_idx: .res 1
pad_zero:.res 1
digits: .res 1
; addr: .res 2
.code .code
;;******************************************************************************** ;;********************************************************************************
;; @function Format a string ;; @function Format a string
;; @details ;; @details
;; If there is no value to be read, the Pz will be set ;; If there is no value to be read, the Pz will be set
;; Formats: ;; Formats:
;; - x: unsigned hex integer (1 byte) -> 2 chars ;; - x: unsigned hex integer (1 byte) -> 2 chars
;; - X: unsigned hex integer (2 byte) -> 4 chars TODO ;; - X: unsigned hex integer (2 byte) -> 4 chars TODO
;; - u: unsigned decimal integer (1 byte) TODO ;; - u: unsigned decimal integer (1 byte) TODO
;; - U: unsigned decimal integer (2 bytes) TODO ;; - U: unsigned decimal integer (2 bytes) TODO
;; - s: null-terminated string (2 bytes ptr)
;; - c: char
;; @param ARG0-1: Format string address ;; @param ARG0-1: Format string address
;; @param ARG2-3: Output string address ;; @param ARG2-3: Output string address
;; @param ARG4+: Additional parameters ;; @param ARG4+: Additional parameters
;; @returns ;; @returns
;; @modifies: A, X, Y, ARG4, ARG5 ;; @modifies: A, X, Y
;;******************************************************************************** ;;********************************************************************************
out_idx := str::out_idx
fmt_idx := str::fmt_idx
.proc strf .proc strf
stz out_idx stz out_idx
stz fmt_idx stz fmt_idx
@ -33,7 +27,7 @@ digits: .res 1
@loop: @loop:
ldy fmt_idx ldy fmt_idx
lda (ARG0),y lda (ARG0),y
jeq @null beq @null
cmp #'%' cmp #'%'
beq @percent beq @percent
@normal_char: ; store A in output string @normal_char: ; store A in output string
@ -48,88 +42,29 @@ digits: .res 1
sty fmt_idx sty fmt_idx
lda (ARG0),y lda (ARG0),y
beq @null beq @null
; padding
cmp #'0'
beq @percent_zero
stz pad_zero
; formats ; formats
cmp #'x' cmp #'x'
beq @format_hex1 beq @format_hex1
cmp #'X'
beq @format_hex2
cmp #'c'
beq @format_char
bra @normal_char bra @normal_char
@percent_zero:
sta pad_zero
bra @percent
; @percent_num:
; sta pad_zero
; bra @percent
@format_hex1: ; 1 byte hex -> 2 chars @format_hex1: ; 1 byte hex -> 2 chars
lda ARG4,x lda ARG4,x
phx phx
jsr str::uint8_to_hex_str jsr str::uint8_to_hex_str
ldy out_idx ldy out_idx
sta (ARG2),y ; most sig digit sta (ARG2),y ; most sig digit
txa
plx
iny iny
beq @out_overflow beq @out_overflow
txa
sta (ARG2),y ; least sig digit sta (ARG2),y ; least sig digit
iny iny
beq @out_overflow beq @out_overflow
sty out_idx sty out_idx
plx
inx ; 1 byte of args handeled inx ; 1 byte of args handeled
bra @format_return ; bra @format_return
@format_return: ; increment fmt_idx to swallow the formating char
@format_hex2: ; 2 byte hex -> 4 chars inc fmt_idx
lda #2 bra @loop
ldy out_idx
jsr str::uint_to_hex_str
bmi @out_overflow ; might also be x overflow
sty out_idx
bra @format_return
@format_char: ; 1 char
lda ARG4,x
ldy out_idx
sta (ARG2),y
inc out_idx
beq @out_overflow
inx
bra @format_return
@format_string: ; string
ldy #0
cpx #0
beq @format_string_loop
; store the pointer to the string at arg4-5
@format_string_move_ptr:
lda ARG4,x
sta ARG4
lda ARG5,x
sta ARG5
@format_string_loop:
lda (ARG4),y
beq @format_string_end ; if null
phy
ldy out_idx
sta (ARG2),y
inc out_idx
beq @out_overflow
ply
iny
@format_string_end:
inx
inx
bra @format_return
@format_return: ; increment fmt_idx to account for the formating char
inc fmt_idx ; at this point, out_idx will always overflow first
jmp @loop
@out_overflow: ; store 0 in last position @out_overflow: ; store 0 in last position
ldy #$ff ldy #$ff
sty out_idx sty out_idx

View File

@ -8,57 +8,25 @@ INCLUDE_UTILITY = 1
.feature underline_in_numbers .feature underline_in_numbers
;;******************************************************************************** ;********************************************************************************
;; @macro Update a byte in memory using a mask ; @macro Update a byte in memory using a mask
;; @param addr Address of the byte to update ; @param addr Address of the byte to update
;; @param value New value ; @param value New value
;; @param mask Mask of the bits to affect by the new value ; @param mask Mask of the bits to affect by the new value
;; @details ; @details
;; 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
;;******************************************************************************** ;********************************************************************************
.macro MaskedWrite addr,value,mask .macro MaskedWrite addr,value,mask
lda value lda #value
eor addr eor addr
and mask and #mask
eor addr eor addr
sta addr sta addr
.endmacro .endmacro
;;********************************************************************************
;; @macro Jump to the subroutine and let the routine return at another location
;; @details
;; By using a indirect address `(addr)` and no ret_val, this macro behaves
;; like an indirect version of jsr.
;; @param addr Target of the jump (can be: `addr`, `(addr)` or `{(addr,x)}`
;; @param ret_addr Return address (optional)
;; @details
;;********************************************************************************
.macro JsrIndirect addr,ret_addr
; -1 because rts increments it
.if .blank(ret_addr)
lda #<(:+ - 1)
pha
lda #>(:+ - 1)
pha
.else
lda #<(ret_addr -1)
pha
lda #>(ret_addr -1)
pha
.endif
jmp addr
.if .blank(ret_addr)
:
.endif
.endmacro
_n_genlabel .set 0 _n_genlabel .set 0
;;******************************************************************************** ;;********************************************************************************
;; @macro Generate a unique label ;; @macro Generate a unique label