Files
aqhomecontrol/avr/modules/spi_hw/main.asm

219 lines
5.1 KiB
NASM

; ***************************************************************************
; copyright : (C) 2025 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
; ***************************************************************************
; macros
; @param @0 register to use
.macro M_SPIHW_MASTER_SEND_BYTE
outr SPDR, @0 ; masterSend Byte
l1_%:
inr @0, SPSR
sbrs @0, SPIF
rjmp l1_%
inr @0, SPDR
.endm
; ***************************************************************************
; defines
.equ SPIHW_MODE_SPEED0_BIT = 0 ; 00=CLK/4, 01=CLK/16
.equ SPIHW_MODE_SPEED1_BIT = 1 ; 10=CLK/64, 11=CLK/128
.equ SPIHW_MODE_DOUBLESPEED_BIT = 2 ; 1=double speed from SPIHW_MODE_SPEED0/1_BIT
.equ SPIHW_MODE_DATAORDER_BIT = 3 ; 1=LSB first, 0=MSB first
.equ SPIHW_MODE_CPOL_BIT = 4 ; 0=leading edge rising/trailing edge falling
.equ SPIHW_MODE_CPHA_BIT = 5 ; 0=sample on leading edge, setup on trailing edge
; ***************************************************************************
; data
.dseg
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine SPIHW_Init @global
;
SPIHW_Init:
sbi SPIHW_SS0_DDR, SPIHW_SS0_PIN ; SS0= output
sbi SPIHW_SS1_DDR, SPIHW_SS1_PIN ; SS1= output
sbi SPIHW_SS2_DDR, SPIHW_SS2_PIN ; SS2= output
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine SPIHW_Fini @global
;
SPIHW_Fini:
ret
; @end
; ---------------------------------------------------------------------------
; @routine SPIHW_MasterStart @global
;
; Start SPI hardware master with the given mode (see @ref SPIHW_MODE_SPEED0_BIT
; and others).
; @param r16 mode
; @param r17 device num (0-7)
; @clobbers r17
SPIHW_MasterStart:
; setup pins
sbi SPIHW_SS_DDR, SPIHW_SS_PIN ; SS : output
sbi SPIHW_MOSI_DDR, SPIHW_MOSI_PIN ; MOSI: output
cbi SPIHW_MISO_DDR, SPIHW_MISO_PIN ; MISO: input
sbi SPIHW_SCK_DDR, SPIHW_SCK_PIN ; SCK: output
; select device
sbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS high
rcall spiHwSelectDevice ; (none)
; cbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS low
; setup SPCR
clr r17
sbrc r16, SPIHW_MODE_DATAORDER_BIT
sbr r17, (1<<DORD)
sbrc r16, SPIHW_MODE_CPOL_BIT
sbr r17, (1<<CPOL)
sbrc r16, SPIHW_MODE_CPHA_BIT
sbr r17, (1<<CPHA)
sbrc r16, SPIHW_MODE_SPEED0_BIT
sbr r17, (1<<SPR0)
sbrc r16, SPIHW_MODE_SPEED1_BIT
sbr r17, (1<<SPR1)
sbr r17, (1<<SPE) | (1<<MSTR)
outr SPCR, r17
; setup SPSR
clr r17
sbrc r16, SPIHW_MODE_DOUBLESPEED_BIT
sbr r17, (1<<SPI2X)
outr SPSR, r17
ret
; @end
; ---------------------------------------------------------------------------
; @routine SPIHW_MasterStop @global
;
; Stop SPI hardware master.
; @clobbers r16
SPIHW_MasterStop:
; sbi SPIHW_SS_OUTPUT, SPIHW_SS_PIN ; SS high
inr r16, SPCR
cbr r16, (1<<SPE)
outr SPCR, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine spiHwSelectDevice
;
; Select given device via SS0-SS2 pins
;
; @param r17=device
; @clobbers none
spiHwSelectDevice:
cbi SPIHW_SS0_OUTPUT, SPIHW_SS0_PIN
sbrc r17, 0
sbi SPIHW_SS0_OUTPUT, SPIHW_SS0_PIN
cbi SPIHW_SS1_OUTPUT, SPIHW_SS1_PIN
sbrc r17, 1
sbi SPIHW_SS1_OUTPUT, SPIHW_SS1_PIN
cbi SPIHW_SS2_OUTPUT, SPIHW_SS2_PIN
sbrc r17, 2
sbi SPIHW_SS2_OUTPUT, SPIHW_SS2_PIN
ret
; @end
; ---------------------------------------------------------------------------
; @routine SPIHW_MasterTransfer @global
;
; Complete transfer sending ony byte and receiving another.
;
; @param r16 byte to send
; @param r16 byte received
; @clobbers none
SPIHW_MasterTransfer:
rcall SPIHW_MasterSendByte ; (none)
rjmp SPIHW_WaitForTransferComplete ; (none)
; @end
; ---------------------------------------------------------------------------
; @routine SPIHW_MasterSendByte @global
;
; Send a byte to the SPI interface. Does not wait for result, you need to
; call @ref SPIHW_WaitForTransferComplete to complete the request and to
; get the response.
; This allows for transfers in background so that the caller can do other stuff
; instead of idly waiting for the transfer to complete.
; However, before calling this routine again you MUST call SPIHW_WaitForTransferComplete!
; @param r16 byte to send
; @clobbers none
SPIHW_MasterSendByte:
outr SPDR, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine SPIHW_WaitForTransferComplete @global
;
; Wait for a transfer to complete and return the byte received.
;
; @return r16 byte received
; @clobbers none
SPIHW_WaitForTransferComplete:
inr r16, SPSR
sbrs r16, SPIF
rjmp SPIHW_WaitForTransferComplete
inr r16, SPDR
ret
; @end