;******************************************************************************** ; @module SPI ; @type driver ; @details ; @depends IO-W65C22N ;******************************************************************************** .include "system/system.s65" .include "programs/print_slow.s65" .ifndef INCLUDE_SPI INCLUDE_SPI = 1 .scope spi_p .zeropage code_page: .res 2 ; SPI_CODE_START + pages_written * 256 .bss bytes_written: .res 1 pages_written: .res 1 .include "util/math.s65" ; spi-transferred code will be placed here .segment "SPI" SPI_CODE_START: lda '$' jsr lcd_char lda #TEST_FMT sta ARG1 lda #TEST_OUT sta ARG3 lda #$a9 sta ARG4 lda #$3c sta ARG5 lda #$10 sta ARG6 jsr strf Print TEST_OUT @spiloop: lda IO1 + IO::RA lda IO2 + IO::RA nop bra @spiloop jmp home ; TODO allocate zp memory fmt_idx = $30 out_idx = $31 ;******************************************************************************** ; @function Format a string ; @details ; If there is no value to be read, the Pz will be set ; Formats: ; - u: unsigned decimal integer (1 byte) ; - U: unsigned decimal integer (2 bytes) ; @param ARG0-1: Format string address ; @param ARG2-3: Output string address ; @param ARG4+: Additional parameters ; @returns ; @modifies: A, Y ;******************************************************************************** .proc strf stz out_idx stz fmt_idx ldy #0 ; position in string ldx #0 ; index of format args @loop: ldy fmt_idx lda (ARG0),y beq @null cmp #'%' beq @percent @normal_char: ; store A in output string ldy out_idx sta (ARG2),y inc fmt_idx inc out_idx beq @out_overflow bra @loop @percent: ; check for format in next position iny sty fmt_idx lda (ARG0),y beq @null ; formats cmp #'x' beq @format_hex1 bra @normal_char @format_hex1: ; 1 byte hex -> 2 chars lda ARG4,x phx jsr int8_to_hex_str ldy out_idx sta (ARG2),y ; most sig digit 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 @out_overflow: ; store 0 in last position ldy #$ff sty out_idx @store_null: lda #0 @null: ; store and return ldy out_idx sta (ARG2),y @rts: rts .endproc ;******************************************************************************** ; @function Convert a 1 byte number into two hex characters ; @param A: Number to convert ; @returns A: Most significant digit ; @returns X: Least significant digit ; @modifies X,Y,A ;******************************************************************************** .proc int8_to_hex_str pha and #%00001111 tay ldx HEX_CHARS,y pla div A,16 and #%00001111 tay lda HEX_CHARS,y rts .endproc HEX_CHARS: .byte "0123456789ABCDEF" TEST_FMT: .asciiz "%x -> %x -> %x:)" TEST_OUT: .asciiz "TESTOUT" ; 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 ; @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 #SPI_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 ; 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 ;******************************************************************************** .proc end ; disable SR interrupts lda #IO::IRQ::SR sta SPI_IO + IO::IER rts .endproc ;******************************************************************************** ; @function Read a byte from SPI ; @details ; Reads a byte from the shift register and stores it in the SPI code buffer ;******************************************************************************** .proc read ldx bytes_written lda SPI_IO + IO::SR sta SPI_CODE_START,x inc bytes_written beq @new_page rts @new_page: inc pages_written inc code_page + 1 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 .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 .endproc .endscope .endif