via.asm (3183B)
1 ;;; Copyright 2021 Gerd Beuster (gerd@frombelow.net). This is free 2 ;;; software under the GNU GPL v3 license or any later version. See 3 ;;; COPYING in the root directory for details. 4 5 via .namespace 6 7 .if SYMON 8 start = $8000 9 .else 10 start = $c800 11 .endif 12 13 ;;; ----------------------------------- 14 ;;; 15 ;;; Generic VIA definitions & operations 16 ;;; 17 ;;; ----------------------------------- 18 19 rb = start 20 ra = start+$1 21 ddrb = start+$2 22 ddra = start+$3 23 t1cl = start+$4 24 t1ch = start+$5 25 t1ll = start+$6 26 t1lh = start+$7 27 t2cl = start+$8 28 t2ch = start+$9 29 sr = start+$a 30 acr = start+$b 31 pcr = start+$c 32 ifr = start+$d 33 ier = start+$e 34 ra2 = start+$f 35 36 ;;; Initialize VIA: Switch all ports to output 37 ;;; and all pins to low, disable interrupts 38 init: 39 lda #$ff 40 sta via.ddra 41 sta via.ddrb 42 lda #$00 43 sta via.ra 44 sta via.rb 45 lda #%01111111 46 sta via.ier ; Disable VIA interrupts 47 lda #$00 48 sta acr ; Disable timers & shift register 49 rts 50 51 52 ;;; ----------------------------------- 53 ;;; 54 ;;; SPI read and write operations 55 ;;; 56 ;;; ----------------------------------- 57 58 59 .section zero_page 60 ;; Used by VIA for (de-)serialization 61 spi_buffer: .byte ? 62 .send zero_page 63 64 ;; Wiring: 65 ;; PA0: CS 66 CS = %00000001 67 ;; PA1: SCK 68 SCK = %00000010 69 ;; PA2: MOSI 70 MOSI = %00000100 71 ;; PA3: MISO 72 MISO = %00001000 73 74 75 76 .section rom 77 78 ;;; Blocking read - read until 79 ;;; byte != $ff is read or retry counter 80 ;;; expires. 81 spi_get: 82 .block 83 ldy #$00 ; Try up to $ff times 84 retry_loop: 85 jsr via.spi_get_nonblocking 86 ;; If we read $ff, we did not receive 87 ;; a byte. 88 cmp #$ff 89 bne done 90 dey ; Try again unless retry 91 bne retry_loop ; counter expired. 92 done: 93 #mem.CLEAR_BITS via.ra, #(MOSI|SCK) ; Set MOSI and SCK low on completion. 94 lda via.spi_buffer 95 rts 96 .bend 97 98 ;;; Return next byte; may be $ff in case of no transmission 99 spi_get_nonblocking: 100 #mem.SET_BITS via.ra, #MOSI ; Keep MOSI high during read 101 lda #$00 ; Clear 102 sta via.spi_buffer ; receive buffer. 103 ldx #$08 ; 8 bit to read. 104 read_bits_loop: 105 .block 106 asl via.spi_buffer ; Make room for next bit 107 #mem.CLEAR_BITS via.ra, #SCK ; Generate clock impulse 108 #mem.SET_BITS via.ra, #SCK 109 lda via.ra ; Get next bit. 110 and #MISO 111 cmp #MISO 112 bne cont ; Nothing to do if we got a zero bit. 113 inc via.spi_buffer ; Set lowest bit in spi_buffer 114 cont: 115 dex 116 bne read_bits_loop 117 #mem.CLEAR_BITS via.ra, #(MOSI|SCK) ; Set MOSI and SCK low on completion. 118 lda via.spi_buffer 119 .if DEBUG 120 phx 121 phy 122 pha 123 #io.PRINTS "< " 124 pla 125 pha 126 jsr io.puth 127 #io.PRINTNL 128 pla 129 ply 130 plx 131 .endif 132 rts 133 .bend 134 135 ;;; Write byte via SPI 136 spi_set: 137 .block 138 .if DEBUG 139 phx 140 phy 141 pha 142 #io.PRINTS "> " 143 pla 144 pha 145 jsr io.puth 146 #io.PRINTNL 147 pla 148 ply 149 plx 150 .endif 151 sta via.spi_buffer ; We send from spi_buffer 152 ldx #$08 ; 8 bit to write 153 write_bits_loop: 154 #mem.CLEAR_BITS via.ra, #SCK ; Set bits on low clock 155 #mem.CLEAR_BITS via.ra,#MOSI 156 lda via.spi_buffer ; Get next bit to send 157 and #%10000000 ; Isolate bit to send. 158 beq cont ; Set MOSI accordingly. 159 #mem.SET_BITS via.ra,#MOSI 160 jmp cont 161 cont: 162 #mem.SET_BITS via.ra, #SCK ; Send bits on high clock 163 asl via.spi_buffer ; Advance to next bit 164 dex 165 bne write_bits_loop 166 #mem.CLEAR_BITS via.ra,#SCK 167 rts 168 .bend 169 170 .send rom 171 172 .endn