use size, add write
This commit is contained in:
parent
5bf82ca844
commit
2d06c9700b
101
spicode.s65
101
spicode.s65
@ -118,56 +118,57 @@ CODE_START:
|
|||||||
bra @loop
|
bra @loop
|
||||||
|
|
||||||
|
|
||||||
kbinit:
|
; .proc kbinit
|
||||||
lda #'['
|
; 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
|
|
||||||
|
|
||||||
|
|
||||||
;; @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
|
; jsr lcd::print_char
|
||||||
lda kb::KB_IO + IO::SR
|
; ; - use the shift register interrupts to read the first 8 bits
|
||||||
sta key_read
|
; ; set shift register to shift in under external clock on CB1
|
||||||
stz kb::KB_IO + IO::SR
|
; ; - configure timer for timing the read of the last 3 bits
|
||||||
|
; ; timer 2 one shot mode is sufficient, leaves T1 available
|
||||||
; disable SR interrupts
|
; lda #(IO::ACR::SR_SIN_PHIE | IO::ACR::T2_IRQ_LOAD)
|
||||||
lda #IO::IRQ::SR
|
; tsb kb::KB_IO + IO::ACR
|
||||||
sta kb::KB_IO + IO::IER
|
; ; the 3 last bits take about 230us, at @1MHz => wait 230 cycles and then the shift register
|
||||||
; enable timer interrupts
|
; lda #230
|
||||||
lda #(IO::IRQ::IRQ | IO::IRQ::T2)
|
; sta kb::KB_IO + IO::T2CL
|
||||||
sta kb::KB_IO + IO::IER
|
; stz key_read
|
||||||
; start timer
|
; stz key_read+1
|
||||||
lda #1
|
; ; enable SR interrupts
|
||||||
sta kb::KB_IO + IO::T2CH
|
; lda #(IO::IRQ::IRQ | IO::IRQ::SR)
|
||||||
; lda #'}'
|
; sta kb::KB_IO + IO::IER
|
||||||
|
; ; load SR to reset
|
||||||
|
; lda kb::KB_IO + IO::SR
|
||||||
|
; lda #']'
|
||||||
; jsr lcd::print_char
|
; jsr lcd::print_char
|
||||||
rts
|
; rts
|
||||||
|
; .endproc
|
||||||
|
|
||||||
|
|
||||||
irq_on_timer:
|
; ;; @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_on_timer
|
||||||
; lda #'<'
|
; lda #'<'
|
||||||
; jsr lcd::print_char
|
; jsr lcd::print_char
|
||||||
lda kb::KB_IO + IO::SR
|
lda kb::KB_IO + IO::SR
|
||||||
@ -201,13 +202,14 @@ irq_on_timer:
|
|||||||
stz key_read+1
|
stz key_read+1
|
||||||
|
|
||||||
rts
|
rts
|
||||||
|
.endproc
|
||||||
|
|
||||||
key_read: .res 2
|
; key_read: .res 2
|
||||||
keycode: .res 1
|
; keycode: .res 1
|
||||||
kb_irq1:
|
kb_irq1:
|
||||||
; lda #'!'
|
; lda #'!'
|
||||||
; jsr lcd::print_char
|
; jsr lcd::print_char
|
||||||
jsr irq_on_shift_reg
|
jsr kb::on_shift_reg_irq
|
||||||
; lda #':'
|
; lda #':'
|
||||||
; jsr lcd::print_char
|
; jsr lcd::print_char
|
||||||
rts
|
rts
|
||||||
@ -215,6 +217,7 @@ kb_irq1:
|
|||||||
kb_irq2:
|
kb_irq2:
|
||||||
; lda #'?'
|
; lda #'?'
|
||||||
; jsr lcd::print_char
|
; jsr lcd::print_char
|
||||||
|
; jsr kb::on_timer_irq
|
||||||
jsr irq_on_timer
|
jsr irq_on_timer
|
||||||
; lda #';'
|
; lda #';'
|
||||||
; jsr lcd::print_char
|
; jsr lcd::print_char
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
; @module SPI
|
;; @module SPI-P
|
||||||
; @type driver
|
;; @type driver
|
||||||
; @details
|
;; @details
|
||||||
; @depends IO-W65C22N
|
;; Support being a peripheral SPI device.
|
||||||
;********************************************************************************
|
;; @depends IO-W65C22N
|
||||||
|
;;********************************************************************************
|
||||||
.ifndef INCLUDE_SPI
|
.ifndef INCLUDE_SPI
|
||||||
INCLUDE_SPI = 1
|
INCLUDE_SPI = 1
|
||||||
|
|
||||||
@ -11,8 +12,15 @@ INCLUDE_SPI = 1
|
|||||||
|
|
||||||
.scope spi_p
|
.scope spi_p
|
||||||
SPI_IO = IO2
|
SPI_IO = IO2
|
||||||
.import CODE_START:absolute
|
Import spi_p, begin_read, irq_read_byte, begin_write, irq_write_byte, end, recv_bytes, sent_bytes, status
|
||||||
Import spi_p, begin, end, read, pages_written, bytes_written
|
|
||||||
|
.enum STATUS
|
||||||
|
XFER_SIZEL = %10000000
|
||||||
|
XFER_SIZEH = %01000000
|
||||||
|
XFER = %00000001
|
||||||
|
DONE = %00000000
|
||||||
|
ERROR = %11111111
|
||||||
|
.endenum
|
||||||
|
|
||||||
.endscope
|
.endscope
|
||||||
.endif ; guard
|
.endif ; guard
|
||||||
|
278
system/spi.s65
278
system/spi.s65
@ -1,69 +1,90 @@
|
|||||||
.include "spi.h65"
|
.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
|
.zeropage
|
||||||
code_page: .res 2 ; CODE_START + pages_written * 256
|
buffer_start: .res 2
|
||||||
.bss
|
.bss
|
||||||
bytes_written: .res 1
|
recv_bytes:
|
||||||
pages_written: .res 1
|
sent_bytes: .res 2
|
||||||
|
status: .res 1
|
||||||
|
buffer_size: .res 2
|
||||||
|
irq_handler: .res 2
|
||||||
|
|
||||||
|
|
||||||
SPI_IO := spi_p::SPI_IO
|
SPI_IO := spi_p::SPI_IO
|
||||||
CODE_START := spi_p::CODE_START
|
|
||||||
|
|
||||||
; 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
|
; .struct SPI_P_Pins
|
||||||
; VIA addresses
|
; ; VIA addresses
|
||||||
DDR_a .word ; address of the data direction register
|
; DDR_a .word ; address of the data direction register
|
||||||
R_a .word ; address of the register
|
; R_a .word ; address of the register
|
||||||
; pin mask
|
; ; pin mask
|
||||||
SCLK_p .byte ; Serial Clock
|
; SCLK_p .byte ; Serial Clock
|
||||||
POCI_p .byte ; Peripheral Out / Controller In
|
; POCI_p .byte ; Peripheral Out / Controller In
|
||||||
PICO_p .byte ; Peripheral In / Controller Out
|
; PICO_p .byte ; Peripheral In / Controller Out
|
||||||
CSB_p .byte ; Chip Select
|
; CSB_p .byte ; Chip Select
|
||||||
; settings
|
; ; settings
|
||||||
CPOL .byte ; Clock Polarity
|
; CPOL .byte ; Clock Polarity
|
||||||
CPHA .byte ; Clock Phase
|
; CPHA .byte ; Clock Phase
|
||||||
.endstruct
|
; .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
|
; store address in zp
|
||||||
lda #<CODE_START
|
lda #<ARG0
|
||||||
sta code_page
|
sta buffer_start
|
||||||
lda #>CODE_START
|
lda #>ARG1
|
||||||
sta code_page + 1
|
sta buffer_start+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
|
|
||||||
|
|
||||||
|
; 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
|
; enable SR interrupts
|
||||||
lda #(IO::IRQ::IRQ | IO::IRQ::SR)
|
lda #(IO::IRQ::IRQ | IO::IRQ::SR)
|
||||||
sta SPI_IO + IO::IER
|
sta SPI_IO + IO::IER
|
||||||
|
|
||||||
; load SR to reset
|
; load SR to reset
|
||||||
lda SPI_IO + IO::SR
|
lda SPI_IO + IO::SR
|
||||||
rts
|
rts
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
; @function Stop listening for SPI transfers
|
;; @function Stop reading/writing from/to SPI
|
||||||
; @details
|
;; @details
|
||||||
; Disables shift register interrupts
|
;; Disables shift register interrupts
|
||||||
; @modifies A
|
;; @modifies A
|
||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
.proc end
|
.proc end
|
||||||
; disable SR interrupts
|
; disable SR interrupts
|
||||||
lda #IO::IRQ::SR
|
lda #IO::IRQ::SR
|
||||||
@ -72,43 +93,154 @@ CODE_START := spi_p::CODE_START
|
|||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
; @function Read a byte from SPI
|
;; @function Read a byte from SPI
|
||||||
; @details
|
;; @details
|
||||||
; Reads a byte from the shift register and stores it in the SPI code buffer
|
;; Reads a byte from the shift register and stores it in the SPI code buffer
|
||||||
; @modifies A,Y
|
;; 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.
|
||||||
.proc read
|
;; If the buffer size given in begin_read is too small too fit the incoming data,
|
||||||
ldy bytes_written
|
;; 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
|
lda SPI_IO + IO::SR
|
||||||
sta (code_page),y
|
bit status
|
||||||
inc bytes_written
|
bmi @read_size1
|
||||||
|
bvs @read_size2
|
||||||
|
ldy recv_bytes
|
||||||
|
sta (buffer_start),y
|
||||||
|
inc recv_bytes
|
||||||
beq @new_page
|
beq @new_page
|
||||||
rts
|
rts
|
||||||
@new_page:
|
@new_page:
|
||||||
inc pages_written
|
inc recv_bytes+1
|
||||||
inc code_page + 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
|
rts
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
; @function Initialize the IO Adapter for SPI
|
;; @function Begin writing to spi
|
||||||
; @param ARG0-1 Address of the SPI_Pins struct
|
;; @details
|
||||||
;********************************************************************************
|
;; - initialize variables
|
||||||
;********************************************************************************
|
;; - configure shift register to shift in under external clock
|
||||||
; @function Read bytes
|
;; - enable shift register interrupts
|
||||||
; @param X Number of bytes to send
|
;; @param ARG0-1: Start address of the buffer
|
||||||
; @param ARG0-1 Address of the SPI_Pins struct
|
;; @param ARG2-3: Size of the buffer
|
||||||
; @param ARG2-3 Address of the first byte
|
;; @todo: Use irq register handler
|
||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
.proc recv_data
|
.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
|
.endproc
|
||||||
;********************************************************************************
|
|
||||||
; @function Send bytes
|
;;;********************************************************************************
|
||||||
; @param X Number of bytes to send
|
;;; @function Write a byte
|
||||||
; @param ARG0-1 Address of the SPI_Pins struct
|
;;; @details
|
||||||
; @param ARG2-3 Address of the first byte
|
;;; Write a byte to the spi shift reister
|
||||||
;********************************************************************************
|
;;; @modifies A,Y
|
||||||
.proc send_data
|
;;;********************************************************************************
|
||||||
|
;.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
|
.endproc
|
||||||
|
Loading…
Reference in New Issue
Block a user