;; vim: filetype=avr
;;
;; SPI interface control and use
;;
.equ SPI_DDR = DDRB
.equ SPI_PORT = PORTB
.equ SPI_SCK = PORTB5
.equ SPI_MISO = PORTB4
.equ SPI_MOSI = PORTB3
.equ SPI_SS = PORTB2
.equ SPI_FLAGS = GPIOR0
.equ SPI_BUSY = 0
;; Initialize SPI subsystem for master operation
SPI_Init:
; Set modes
sbi SPI_DDR, SPI_SCK ; Out
sbi SPI_DDR, SPI_MOSI ; Out
sbi SPI_DDR, SPI_SS ; Out
; Drive SS high (off)
sbi SPI_PORT, SPI_SS
; Set control mode
; Enable interrupt
; Enable SPI
; MSB first
; Master mode
; Polarity/phase: Mode 0 (sample on rising edge)
; Clock rate 1/16
ldi r16, (1 << SPIE) | (1 << SPE) | (0 << DORD) | (1 << MSTR) | (0 << CPOL) | (0 << CPHA) | (0b01 << SPR0)
out SPCR, r16
; Flags
clr r0
out SPI_FLAGS, r0
; Done
ret
;; Send byte
;; Input: r16
;; XXX: should not be busy...
SPI_SendRecv:
; Flag
sbi SPI_FLAGS, SPI_BUSY
; Enable slave (low)
cbi SPI_PORT, SPI_SS
; Write byte (starts SCK)
out SPDR, r16
; Wait for interrupt
; Done
ret
;; Wait for byte to be sent
SPI_Wait:
sbic SPI_FLAGS, SPI_BUSY ; Test for busy flag
rjmp SPI_Wait ; loop
; Done
ret
;; Service SPI interrupt
SPI_Interrupt:
; Store SREG
in r16, SREG
; Drive SS high (off)
sbi SPI_PORT, SPI_SS
; Read
in r10, SPDR
; Flag
cbi SPI_FLAGS, SPI_BUSY
; Done
out SREG, r16
reti