use size, add write
This commit is contained in:
parent
5bf82ca844
commit
2d06c9700b
99
spicode.s65
99
spicode.s65
@ -118,56 +118,57 @@ CODE_START:
|
||||
bra @loop
|
||||
|
||||
|
||||
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
|
||||
; .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
|
||||
irq_on_shift_reg:
|
||||
; lda #'{'
|
||||
; jsr lcd::print_char
|
||||
lda kb::KB_IO + IO::SR
|
||||
sta key_read
|
||||
stz kb::KB_IO + IO::SR
|
||||
; ;; @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
|
||||
; ; 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
|
||||
|
||||
|
||||
irq_on_timer:
|
||||
.proc irq_on_timer
|
||||
; lda #'<'
|
||||
; jsr lcd::print_char
|
||||
lda kb::KB_IO + IO::SR
|
||||
@ -201,13 +202,14 @@ irq_on_timer:
|
||||
stz key_read+1
|
||||
|
||||
rts
|
||||
.endproc
|
||||
|
||||
key_read: .res 2
|
||||
keycode: .res 1
|
||||
; key_read: .res 2
|
||||
; keycode: .res 1
|
||||
kb_irq1:
|
||||
; lda #'!'
|
||||
; jsr lcd::print_char
|
||||
jsr irq_on_shift_reg
|
||||
jsr kb::on_shift_reg_irq
|
||||
; lda #':'
|
||||
; jsr lcd::print_char
|
||||
rts
|
||||
@ -215,6 +217,7 @@ kb_irq1:
|
||||
kb_irq2:
|
||||
; lda #'?'
|
||||
; jsr lcd::print_char
|
||||
; jsr kb::on_timer_irq
|
||||
jsr irq_on_timer
|
||||
; lda #';'
|
||||
; jsr lcd::print_char
|
||||
|
@ -1,9 +1,10 @@
|
||||
;********************************************************************************
|
||||
; @module SPI
|
||||
; @type driver
|
||||
; @details
|
||||
; @depends IO-W65C22N
|
||||
;********************************************************************************
|
||||
;;********************************************************************************
|
||||
;; @module SPI-P
|
||||
;; @type driver
|
||||
;; @details
|
||||
;; Support being a peripheral SPI device.
|
||||
;; @depends IO-W65C22N
|
||||
;;********************************************************************************
|
||||
.ifndef INCLUDE_SPI
|
||||
INCLUDE_SPI = 1
|
||||
|
||||
@ -11,8 +12,15 @@ INCLUDE_SPI = 1
|
||||
|
||||
.scope spi_p
|
||||
SPI_IO = IO2
|
||||
.import CODE_START:absolute
|
||||
Import spi_p, begin, end, read, pages_written, bytes_written
|
||||
Import spi_p, begin_read, irq_read_byte, begin_write, irq_write_byte, end, recv_bytes, sent_bytes, status
|
||||
|
||||
.enum STATUS
|
||||
XFER_SIZEL = %10000000
|
||||
XFER_SIZEH = %01000000
|
||||
XFER = %00000001
|
||||
DONE = %00000000
|
||||
ERROR = %11111111
|
||||
.endenum
|
||||
|
||||
.endscope
|
||||
.endif ; guard
|
||||
|
280
system/spi.s65
280
system/spi.s65
@ -1,69 +1,90 @@
|
||||
.include "spi.h65"
|
||||
|
||||
Export spi_p, begin, end, read, pages_written, bytes_written
|
||||
Export spi_p, begin_read, irq_read_byte, begin_write, irq_write_byte, end, recv_bytes, sent_bytes, status, spi_irq
|
||||
|
||||
.zeropage
|
||||
code_page: .res 2 ; CODE_START + pages_written * 256
|
||||
buffer_start: .res 2
|
||||
.bss
|
||||
bytes_written: .res 1
|
||||
pages_written: .res 1
|
||||
recv_bytes:
|
||||
sent_bytes: .res 2
|
||||
status: .res 1
|
||||
buffer_size: .res 2
|
||||
irq_handler: .res 2
|
||||
|
||||
|
||||
SPI_IO := spi_p::SPI_IO
|
||||
CODE_START := spi_p::CODE_START
|
||||
|
||||
; 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
|
||||
; .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
|
||||
;; @details
|
||||
;; The transfer must be: <SIZE, >SIZE, data (SIZE bytes)
|
||||
;;
|
||||
;; - initialize variables
|
||||
;; - configure shift register to shift in under external clock
|
||||
;; - enable shift register interrupts
|
||||
;; @param ARG0-1: Start address of the buffer
|
||||
;; @param ARG2-3: Size of the buffer
|
||||
;; @todo: Use irq register handler
|
||||
;; @note: The buffer must be large enough for the received data.
|
||||
;;********************************************************************************
|
||||
.proc begin_read
|
||||
stz recv_bytes
|
||||
stz recv_bytes+1
|
||||
lda #%spi_p::STATUS::XFER_SIZEL
|
||||
sta status
|
||||
|
||||
;********************************************************************************
|
||||
; @function Begin listening for SPI transfers
|
||||
; @details
|
||||
; - initialize variables
|
||||
; - configure shift register to shift in under external clock
|
||||
; - enable shift register interrupts
|
||||
;********************************************************************************
|
||||
.proc begin
|
||||
stz pages_written
|
||||
stz bytes_written
|
||||
; store address in zp
|
||||
lda #<CODE_START
|
||||
sta code_page
|
||||
lda #>CODE_START
|
||||
sta code_page + 1
|
||||
; todo USE MASKS
|
||||
; set Shift register to shift in under external clock on CB1
|
||||
lda #IO::ACR::SR_SIN_PHIE
|
||||
sta SPI_IO + IO::ACR
|
||||
lda #<ARG0
|
||||
sta buffer_start
|
||||
lda #>ARG1
|
||||
sta buffer_start+1
|
||||
|
||||
; load irq handler
|
||||
lda #<irq_read_byte
|
||||
sta irq_handler
|
||||
lda #>irq_read_byte
|
||||
sta irq_handler+1
|
||||
|
||||
; temporarily store the low byte in buffer, will be checked later
|
||||
lda #<ARG2
|
||||
sta (buffer_start)
|
||||
lda #>ARG3
|
||||
sta buffer_size+1
|
||||
; 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
|
||||
; enable SR interrupts
|
||||
lda #(IO::IRQ::IRQ | IO::IRQ::SR)
|
||||
sta SPI_IO + IO::IER
|
||||
|
||||
; load SR to reset
|
||||
lda SPI_IO + IO::SR
|
||||
rts
|
||||
.endproc
|
||||
|
||||
|
||||
;********************************************************************************
|
||||
; @function Stop listening for SPI transfers
|
||||
; @details
|
||||
; Disables shift register interrupts
|
||||
; @modifies A
|
||||
;********************************************************************************
|
||||
;;********************************************************************************
|
||||
;; @function Stop reading/writing from/to SPI
|
||||
;; @details
|
||||
;; Disables shift register interrupts
|
||||
;; @modifies A
|
||||
;;********************************************************************************
|
||||
.proc end
|
||||
; disable SR interrupts
|
||||
lda #IO::IRQ::SR
|
||||
@ -72,43 +93,154 @@ CODE_START := spi_p::CODE_START
|
||||
.endproc
|
||||
|
||||
|
||||
;********************************************************************************
|
||||
; @function Read a byte from SPI
|
||||
; @details
|
||||
; Reads a byte from the shift register and stores it in the SPI code buffer
|
||||
; @modifies A,Y
|
||||
;********************************************************************************
|
||||
.proc read
|
||||
ldy bytes_written
|
||||
;;********************************************************************************
|
||||
;; @function Read a byte from SPI
|
||||
;; @details
|
||||
;; Reads a byte from the shift register and stores it in the SPI code buffer
|
||||
;; The first two bytes must be the size of the incumong data (LE).
|
||||
;; The spi_p:status is updated according to the current stage of the transfer.
|
||||
;; If the buffer size given in begin_read is too small too fit the incoming data,
|
||||
;; the status is set to ERROR and spi (shift register) interrupts are disabled before
|
||||
;; the first real byte is read.
|
||||
;; @modifies A,Y
|
||||
;;********************************************************************************
|
||||
.proc irq_read_byte
|
||||
lda SPI_IO + IO::SR
|
||||
sta (code_page),y
|
||||
inc bytes_written
|
||||
bit status
|
||||
bmi @read_size1
|
||||
bvs @read_size2
|
||||
ldy recv_bytes
|
||||
sta (buffer_start),y
|
||||
inc recv_bytes
|
||||
beq @new_page
|
||||
rts
|
||||
@new_page:
|
||||
inc pages_written
|
||||
inc code_page + 1
|
||||
inc recv_bytes+1
|
||||
inc buffer_start+1
|
||||
rts
|
||||
@read_size1:
|
||||
sta buffer_size
|
||||
lda #spi_p::STATUS::XFER_SIZEH
|
||||
sta status
|
||||
rts
|
||||
@read_size2:
|
||||
; todo: check if the buffer is large enough:
|
||||
; low byte of buffer size in (buffer_start), high byte in buffer_size+1
|
||||
; low byte of recv buffer size in buffer_size, high byte in A
|
||||
cmp buffer_size+1
|
||||
beq @hieq
|
||||
sta buffer_size+1
|
||||
bcs @enough ; buffer larger
|
||||
bra @not_enough
|
||||
@hieq: ; high bytes are equal, check lo
|
||||
lda (buffer_start)
|
||||
cmp buffer_size
|
||||
bcs @enough
|
||||
@not_enough:
|
||||
lda #spi_p::STATUS::ERROR
|
||||
sta status
|
||||
; disable SR interrupts
|
||||
lda #IO::IRQ::SR
|
||||
sta SPI_IO + IO::IER
|
||||
rts
|
||||
@enough:
|
||||
lda #spi_p::STATUS::XFER
|
||||
sta status
|
||||
rts
|
||||
.endproc
|
||||
|
||||
|
||||
;********************************************************************************
|
||||
; @function Initialize the IO Adapter for SPI
|
||||
; @param ARG0-1 Address of the SPI_Pins struct
|
||||
;********************************************************************************
|
||||
;********************************************************************************
|
||||
; @function Read bytes
|
||||
; @param X Number of bytes to send
|
||||
; @param ARG0-1 Address of the SPI_Pins struct
|
||||
; @param ARG2-3 Address of the first byte
|
||||
;********************************************************************************
|
||||
.proc recv_data
|
||||
|
||||
;;********************************************************************************
|
||||
;; @function Begin writing to spi
|
||||
;; @details
|
||||
;; - initialize variables
|
||||
;; - configure shift register to shift in under external clock
|
||||
;; - enable shift register interrupts
|
||||
;; @param ARG0-1: Start address of the buffer
|
||||
;; @param ARG2-3: Size of the buffer
|
||||
;; @todo: Use irq register handler
|
||||
;;********************************************************************************
|
||||
.proc begin_write
|
||||
stz recv_bytes
|
||||
stz recv_bytes+1
|
||||
; store address in zp
|
||||
lda #<ARG0
|
||||
sta buffer_start
|
||||
lda #>ARG1
|
||||
sta buffer_start+1
|
||||
; store size
|
||||
lda #<ARG2
|
||||
sta buffer_size
|
||||
lda #>ARG3
|
||||
sta buffer_size+1
|
||||
; load irq handler
|
||||
lda #<irq_read_byte
|
||||
sta irq_handler
|
||||
lda #>irq_read_byte
|
||||
sta irq_handler+1
|
||||
; set Shift register to shift out under external clock on CB1
|
||||
MaskedWrite SPI_IO+IO::ACR, #IO::ACR::SR_SOUT_PHIE, #IO::ACR_MASK::SR
|
||||
; enable SR interrupts
|
||||
lda #(IO::IRQ::IRQ | IO::IRQ::SR)
|
||||
sta SPI_IO + IO::IER
|
||||
; write the first byte
|
||||
@write_size1:
|
||||
lda buffer_size
|
||||
sta SPI_IO+IO_SR
|
||||
lda #spi_p::STATUS::XFER_SIZEH
|
||||
sta status
|
||||
rts
|
||||
rts
|
||||
.endproc
|
||||
;********************************************************************************
|
||||
; @function Send bytes
|
||||
; @param X Number of bytes to send
|
||||
; @param ARG0-1 Address of the SPI_Pins struct
|
||||
; @param ARG2-3 Address of the first byte
|
||||
;********************************************************************************
|
||||
.proc send_data
|
||||
|
||||
;;;********************************************************************************
|
||||
;;; @function Write a byte
|
||||
;;; @details
|
||||
;;; Write a byte to the spi shift reister
|
||||
;;; @modifies A,Y
|
||||
;;;********************************************************************************
|
||||
;.proc irq_write_byte
|
||||
; ldy sent_bytes
|
||||
; lda (buffer_start),y
|
||||
; sta SPI_IO + IO::SR
|
||||
; inc sent_bytes
|
||||
; beq @new_page
|
||||
; rts
|
||||
;@new_page:
|
||||
; inc sent_bytes+1
|
||||
; inc buffer_start+1
|
||||
; rts
|
||||
;.endproc
|
||||
|
||||
|
||||
;;********************************************************************************
|
||||
;; @function Write a byte to SPI
|
||||
;; @details
|
||||
;; Write a byte from the buffer to the (spi) shift register.
|
||||
;; The first two bytes are the size of the data (LE).
|
||||
;; The spi_p:status is updated according to the current stage of the transfer.
|
||||
;; @modifies A,Y
|
||||
;;********************************************************************************
|
||||
.proc irq_write_byte
|
||||
bit status
|
||||
bvs @write_size2 ; bit 6 set -> XFER_SIZEH
|
||||
ldy sent_bytes
|
||||
lda (buffer_start),y
|
||||
sta SPI_IO + IO::SR
|
||||
inc sent_bytes
|
||||
beq @new_page
|
||||
rts
|
||||
@new_page:
|
||||
inc sent_bytes+1
|
||||
inc buffer_start+1
|
||||
rts
|
||||
@write_size2:
|
||||
lda buffer_size+1
|
||||
sta SPI_IO+IO_SR
|
||||
lda #spi_p::STATUS::XFER
|
||||
sta status
|
||||
rts
|
||||
.endproc
|
||||
|
||||
|
||||
.endproc
|
||||
|
Loading…
Reference in New Issue
Block a user