spi.inc
author Tero Marttila <terom@fixme.fi>
Sat, 08 May 2010 20:07:18 +0300
changeset 21 95549ce0e3da
parent 18 79b25e81721f
child 23 a6afc0eb347f
permissions -rw-r--r--
timer: try and actually sleep
;; 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