From 3d773390bf7cb26f23aa4b0d297657229b094584 Mon Sep 17 00:00:00 2001 From: "Matthias@Dell" Date: Wed, 27 Dec 2023 16:56:14 +0100 Subject: [PATCH] wip --- main.s65 | 22 ++++---- programs/spi-menu.s65 | 65 ++++++++++++++--------- spicode.s65 | 26 +++++----- system/irq_handler.h65 | 8 +-- system/lcd.s65 | 2 +- system/spi.h65 | 18 ++++++- system/spi.s65 | 34 ++++++------ util/string-conversion.s65 | 51 +++++++++++++++++- util/string.h65 | 8 ++- util/string.s65 | 103 ++++++++++++++++++++++++++++++------- utility.h65 | 56 +++++++++++++++----- 11 files changed, 280 insertions(+), 113 deletions(-) diff --git a/main.s65 b/main.s65 index ff670cd..3ef7a71 100644 --- a/main.s65 +++ b/main.s65 @@ -65,7 +65,7 @@ irq: @irq_io1: lda IO1 + IO::IFR sta irq_via_ifr - bbr7 irq_via_ifr,@irq_io2 ; skip + bbr7 irq_via_ifr,@irq_io1 ; skip bbs2 irq_via_ifr,@irq_kb1 ; shit reg -> first 8 bits bbs5 irq_via_ifr,@irq_kb2 ; timer -> last 3 bits @irq_io2: @@ -74,6 +74,7 @@ irq: bbr7 irq_via_ifr,@irq_return ; skip bbs2 irq_via_ifr,@irq_spi_p ; check SR bbs1 irq_via_ifr,@irq_keypad ; check CA1 + ; this SHOULD never be reached jsr lcd::clear Print "Unknown IRQ" @@ -81,23 +82,18 @@ irq: lda #$ff sta IO1 + IO::IFR sta IO2 + IO::IFR - rti - ; bra @irq_return -@irq_keypad: - lda #<@irq_return - pha - lda #>@irq_return - pha - jmp (spi_p::irq_handler) -@irq_spi_p: - jsr spi_p::read bra @irq_return +@irq_keypad: + jsr kp::read_irq + bra @irq_return +@irq_spi_p: + JsrIndirect (spi_p::irq_handler), @irq_return @irq_kb1: - ; PrintNC "<30>" + Print "$3000" jsr $3000 bra @irq_return @irq_kb2: - ; PrintNC "<31>" + Print "$3100" jsr $3100 bra @irq_return ; @irq_dht: diff --git a/programs/spi-menu.s65 b/programs/spi-menu.s65 index a75ed94..f036ee4 100644 --- a/programs/spi-menu.s65 +++ b/programs/spi-menu.s65 @@ -4,43 +4,56 @@ .include "lcd.h65" .include "chars.h65" .import home:absolute -.import SPI_IO +.import CODE_START: absolute +.import __SPI_SIZE__ .export spi_menu .bss -trans_bytes: .res 1 -trans_pages: .res 1 -status: .res 1 +trans_bytes: .res 2 ; used to check if screen needs to be updated +status_char: .res 1 status_str: .res 17 ; 16 + null .code .proc spi_menu stz trans_bytes - stz trans_pages - lda #'X' - sta status + stz trans_bytes+1 @print_menu: jsr lcd::clear 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: lda #lcd::LINE4 jsr lcd::set_position - Strf FMT_STATUS,status_str,trans_pages,trans_bytes,status + Strf "%x%xb Status: %c",status_str,trans_bytes+1,trans_bytes,status_char PrintNC status_str @loop: ; check if a byte has been transferred -@check_byte: - lda spi_p::bytes_written +@check_received: + lda spi_p::recv_bytes cmp trans_bytes beq @read_keypad -@byte_written: +@byte_received: sta trans_bytes -@check_page: - lda spi_p::pages_written - cmp trans_pages - beq @read_keypad -@page_written: - sta trans_pages + lda spi_p::recv_bytes+1 + lda trans_bytes+1 bra @print_status @read_keypad: lda kp::_DEBUG_VAL @@ -57,22 +70,26 @@ status_str: .res 17 ; 16 + null beq @spi_end cmp #'C' beq @spi_jump - bra @loop + bra @update_status ; any other key @spi_begin: - lda #'@' - sta status - jsr spi_p::begin + lda #CODE_START + sta ARG1 + lda #<__SPI_SIZE__ + sta ARG2 + lda #>__SPI_SIZE__ + sta ARG3 + jsr spi_p::begin_read jmp @print_menu @spi_end: - lda #'X' - sta status jsr spi_p::end jmp @print_menu @spi_jump: jsr spi_p::end jsr lcd::clear Print START - jmp spi_p::CODE_START + jmp CODE_START @return_home: jsr spi_p::end jmp home diff --git a/spicode.s65 b/spicode.s65 index 51163da..f8fb77d 100644 --- a/spicode.s65 +++ b/spicode.s65 @@ -3,6 +3,7 @@ .include "lcd.h65" .include "math.h65" .include "keypad.h65" +.include "keyboard.h65" .include "chars.h65" .import homeloop:absolute .import home:absolute @@ -12,9 +13,6 @@ .import memcopy -.scope kb -KB_IO = IO1 -.endscope CODE_START: @@ -60,7 +58,7 @@ CODE_START: ; PrintNC $3000 - jsr kbinit + jsr kb::init lda #'%' jsr lcd::print_char @@ -110,7 +108,7 @@ CODE_START: jsr lcd::print_char bra @loop @lB: - Strf fmt_str, out_str, keycode + Strf fmt_str, out_str, kb::keycode Print out_str bra @loop @lC: @@ -168,11 +166,11 @@ CODE_START: ; .endproc -.proc irq_on_timer +.proc irq_timer_handler ; lda #'<' ; jsr lcd::print_char lda kb::KB_IO + IO::SR - sta key_read + 1 + sta kb::key_read + 1 lda kb::KB_IO + IO::T2CL ; clear interrupt flag @@ -190,16 +188,16 @@ CODE_START: ror ror ror - lda key_read ; not affecting carry + 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 keycode + sta kb::keycode - Strf fmt_str2, out_str, keycode, key_read, key_read+1 + Strf fmt_str2, out_str, kb::keycode, kb::key_read, kb::key_read+1 PrintNC out_str - stz key_read - stz key_read+1 + stz kb::key_read + stz kb::key_read+1 rts .endproc @@ -209,7 +207,7 @@ CODE_START: kb_irq1: ; lda #'!' ; jsr lcd::print_char - jsr kb::on_shift_reg_irq + jsr kb::irq_shift_reg_handler ; lda #':' ; jsr lcd::print_char rts @@ -218,7 +216,7 @@ kb_irq2: ; lda #'?' ; jsr lcd::print_char ; jsr kb::on_timer_irq - jsr irq_on_timer + jsr irq_timer_handler ; lda #';' ; jsr lcd::print_char rts diff --git a/system/irq_handler.h65 b/system/irq_handler.h65 index 07fcaf6..1964091 100644 --- a/system/irq_handler.h65 +++ b/system/irq_handler.h65 @@ -1,7 +1,7 @@ -;******************************************************************************** -; @module irq_handler -; @type system -;******************************************************************************** +;;******************************************************************************** +;; @module irq_handler +;; @type system +;;******************************************************************************** .ifndef INCLUDE_IRQ_HANDLER INCLUDE_IRQ_HANDLER = 1 diff --git a/system/lcd.s65 b/system/lcd.s65 index 7e19bbc..6912da7 100644 --- a/system/lcd.s65 +++ b/system/lcd.s65 @@ -22,7 +22,7 @@ charcount: .res 1 lda #$ff ; RB 0-7 output 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 ; sta lcd::LCD_IO+IO::DDRA diff --git a/system/spi.h65 b/system/spi.h65 index b93c4b0..26fa136 100644 --- a/system/spi.h65 +++ b/system/spi.h65 @@ -12,7 +12,9 @@ INCLUDE_SPI = 1 .scope spi_p SPI_IO = IO2 -Import spi_p, begin_read, irq_read_byte, begin_write, irq_write_byte, end, recv_bytes, sent_bytes, status +Import spi_p, irq_handler, end, status +Import spi_p, begin_read, irq_read_byte, recv_bytes +Import spi_p, begin_write, irq_write_byte, sent_bytes .enum STATUS XFER_SIZEL = %10000000 @@ -24,3 +26,17 @@ Import spi_p, begin_read, irq_read_byte, begin_write, irq_write_byte, end, recv_ .endscope .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 diff --git a/system/spi.s65 b/system/spi.s65 index 7e60d83..652ddaa 100644 --- a/system/spi.s65 +++ b/system/spi.s65 @@ -1,6 +1,9 @@ .include "spi.h65" +.include "system.h65" -Export spi_p, begin_read, irq_read_byte, begin_write, irq_write_byte, end, recv_bytes, sent_bytes, status, spi_irq +Export spi_p, irq_handler, end, status +Export spi_p, begin_read, irq_read_byte, recv_bytes +Export spi_p, begin_write, irq_write_byte, sent_bytes .zeropage buffer_start: .res 2 @@ -17,19 +20,14 @@ SPI_IO := spi_p::SPI_IO ; spi-transferred code will be placed here ; SPI_P = as peripheral .code -; .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 + +;;******************************************************************************** +;; @function Begin listening for SPI transfers +;;******************************************************************************** +.proc init + lda #spi_p::STATUS::DONE + sta status +.endproc ;;******************************************************************************** @@ -48,7 +46,7 @@ SPI_IO := spi_p::SPI_IO .proc begin_read stz recv_bytes stz recv_bytes+1 - lda #%spi_p::STATUS::XFER_SIZEL + lda #spi_p::STATUS::XFER_SIZEL sta status ; store address in zp @@ -186,7 +184,7 @@ SPI_IO := spi_p::SPI_IO ; write the first byte @write_size1: lda buffer_size - sta SPI_IO+IO_SR + sta SPI_IO+IO::SR lda #spi_p::STATUS::XFER_SIZEH sta status rts @@ -236,11 +234,9 @@ SPI_IO := spi_p::SPI_IO rts @write_size2: lda buffer_size+1 - sta SPI_IO+IO_SR + sta SPI_IO+IO::SR lda #spi_p::STATUS::XFER sta status rts .endproc - -.endproc diff --git a/util/string-conversion.s65 b/util/string-conversion.s65 index 71f006c..f621ca3 100644 --- a/util/string-conversion.s65 +++ b/util/string-conversion.s65 @@ -1,6 +1,6 @@ .include "string.h65" .include "math.h65" -Export str,hex_char_to_uint8, hex_str_to_uint, uint8_to_hex_str +Export str,hex_char_to_uint8, hex_str_to_uint, uint8_to_hex_str, uint_to_hex_str .code ; @@ -130,6 +130,55 @@ Export str,hex_char_to_uint8, hex_str_to_uint, uint8_to_hex_str .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 HEX_CHARS_UPPER: .byte "0123456789ABCDEF" HEX_CHARS_LOWER: .byte "0123456789abcdef" diff --git a/util/string.h65 b/util/string.h65 index b0e2108..0c88298 100644 --- a/util/string.h65 +++ b/util/string.h65 @@ -12,7 +12,8 @@ INCLUDE_STRING = 1 .scope str Import str, strf -Import str, hex_char_to_uint8, hex_str_to_uint, uint8_to_hex_str +Import str, hex_char_to_uint8, hex_str_to_uint +Import str, uint8_to_hex_str, uint_to_hex_str .macro _StrfStoreArg arg @@ -35,7 +36,7 @@ Import str, hex_char_to_uint8, hex_str_to_uint, uint8_to_hex_str ;; @param out: Output string address ;; @param x0-x9: Additional parameters ;; @warning Addresses as additional paramters must be passed like this `#addr` -;; @modifies: A, X, Y +;; @modifies: A, X, Y, ARG4, ARG5 ;; @see strf ;;******************************************************************************** .macro Strf fmt,out,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9 @@ -73,8 +74,5 @@ Import str, hex_char_to_uint8, hex_str_to_uint, uint8_to_hex_str ; .out .sprintf("info: Strf: called with %d arguments", @N_ARGS) .endmacro -; TODO allocate zp memory -fmt_idx = $30 -out_idx = $31 .endscope .endif ; guard diff --git a/util/string.s65 b/util/string.s65 index 7f1cd7a..c726764 100644 --- a/util/string.s65 +++ b/util/string.s65 @@ -1,24 +1,30 @@ .include "string.h65" Export str, strf +.zeropage +fmt_idx: .res 1 +out_idx: .res 1 +pad_zero:.res 1 +digits: .res 1 +; addr: .res 2 .code ;;******************************************************************************** ;; @function Format a string ;; @details -;; If there is no value to be read, the Pz will be set -;; Formats: -;; - x: unsigned hex integer (1 byte) -> 2 chars -;; - X: unsigned hex integer (2 byte) -> 4 chars TODO -;; - u: unsigned decimal integer (1 byte) TODO -;; - U: unsigned decimal integer (2 bytes) TODO +;; If there is no value to be read, the Pz will be set +;; Formats: +;; - x: unsigned hex integer (1 byte) -> 2 chars +;; - X: unsigned hex integer (2 byte) -> 4 chars TODO +;; - u: unsigned decimal integer (1 byte) TODO +;; - U: unsigned decimal integer (2 bytes) TODO +;; - s: null-terminated string (2 bytes ptr) +;; - c: char ;; @param ARG0-1: Format string address ;; @param ARG2-3: Output string address ;; @param ARG4+: Additional parameters ;; @returns -;; @modifies: A, X, Y +;; @modifies: A, X, Y, ARG4, ARG5 ;;******************************************************************************** -out_idx := str::out_idx -fmt_idx := str::fmt_idx .proc strf stz out_idx stz fmt_idx @@ -27,7 +33,7 @@ fmt_idx := str::fmt_idx @loop: ldy fmt_idx lda (ARG0),y - beq @null + jeq @null cmp #'%' beq @percent @normal_char: ; store A in output string @@ -42,29 +48,88 @@ fmt_idx := str::fmt_idx sty fmt_idx lda (ARG0),y beq @null + ; padding + cmp #'0' + beq @percent_zero + stz pad_zero ; formats cmp #'x' beq @format_hex1 + cmp #'X' + beq @format_hex2 + cmp #'c' + beq @format_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 lda ARG4,x phx - jsr str::uint8_to_hex_str - ldy out_idx - sta (ARG2),y ; most sig digit + jsr str::uint8_to_hex_str + ldy out_idx + sta (ARG2),y ; most sig digit + txa + plx iny beq @out_overflow - txa sta (ARG2),y ; least sig digit iny beq @out_overflow sty out_idx - plx inx ; 1 byte of args handeled - ; bra @format_return -@format_return: ; increment fmt_idx to swallow the formating char - inc fmt_idx - bra @loop + bra @format_return + +@format_hex2: ; 2 byte hex -> 4 chars + lda #2 + 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 ldy #$ff sty out_idx diff --git a/utility.h65 b/utility.h65 index 6463add..640dce7 100644 --- a/utility.h65 +++ b/utility.h65 @@ -8,25 +8,57 @@ INCLUDE_UTILITY = 1 .feature underline_in_numbers -;******************************************************************************** -; @macro Update a byte in memory using a mask -; @param addr Address of the byte to update -; @param value New value -; @param mask Mask of the bits to affect by the new value -; @details -; 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 -; xor result with addr -> flips selected bits -;******************************************************************************** +;;******************************************************************************** +;; @macro Update a byte in memory using a mask +;; @param addr Address of the byte to update +;; @param value New value +;; @param mask Mask of the bits to affect by the new value +;; @details +;; 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 +;; xor result with addr -> flips selected bits +;;******************************************************************************** .macro MaskedWrite addr,value,mask - lda #value + lda value eor addr - and #mask + and mask eor addr sta addr .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 ;;******************************************************************************** ;; @macro Generate a unique label