;*******************************************************************************;
;*                                                                              ;
;*  This implements a generic library functionality to support SPI              ;
;*  for PIC18 family                                                            ;
;*  It adds additional functionality of Rx/Tx user defined Cicular buffer       ;
;*                                                                              ;
;*******************************************************************************;
;* FileName:            18SPISI.asm                                     ;
;* Dependencies:        P18xxx.inc                                      ;
;*                      SPISInt.Inc                                     ;
;* Processor:           PIC18xxxx                                       ;
;* Assembler:           MPASMWIN 02.70.02 or higher                     ;
;* Linker:              MPLINK 2.33.00 or higher                        ;
;* Company:             Microchip Technology, Inc.                      ;
;*                                                                      ;
;* Software License Agreement                                           ;
;*                                                                      ;
;* The software supplied herewith by Microchip Technology Incorporated  ;
;* (the "Company") for its PICmicro Microcontroller is Polended and    ;
;* supplied to you, the Company's customer, for use solely and          ;
;* exclusively on Microchip PICmicro Microcontroller products. The      ;
;* software is owned by the Company and/or its supplier, and is         ;
;* protected under applicable copyright laws. All rights are reserved.  ;
;* Any use in violation of the foregoing restrictions may subject the   ;
;* user to criminal sanctions under applicable laws, as well as to      ;
;* civil liability for the breach of the terms and conditions of this   ;
;* license.                                                             ;
;*                                                                      ;
;* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,    ;
;* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED    ;
;* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A          ;
;* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,    ;
;* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR           ;
;* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.                    ;
;*                                                                      ;
;*                                                                      ;
;* ANY SPECIAL DESCRIPTION THAT MIGHT BE USEFUL FOR THIS FILE.          ;
;*                                                                      ;
;* Author               Date            Comment                         ;
;*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;* Vidyadhar       May 14, 2003    Initial Release (V1.0)               ;
;*                                                                      ;
;***********************************************************************;


;***********************************************************************;
SPISIntCODE   CODE                                                      ;
                                                                        ;
;***********************************************************************;
; Function: SPISIntInit                                                 ;
;                                                                       ;
; PreCondition: None                                                    ;
;                                                                       ;
; Overview:                                                             ;
;       This routine is used for MSSP/SSP/BSSP Module Initialization    ;
;       It initializes Module according to compile time selection and   ;
;       flushes the Rx and Tx buffer. It clears all SPI errors          ;
;                                                                       ;
; Input: CLM options                                                    ;
;                                                                       ;
;                                                                       ;
; Output: None                                                          ;
;                                                                       ;
; Side Effects: Bank selection bits and 'W' register are changed        ;
;                                                                       ;
; Stack requirement: 1 level deep                                       ;
;                                                                       ;
;***********************************************;***********************;
                                                ;
SPISIntInit:                                    ;
                                                ;
        GLOBAL  SPISIntInit                     ;
                                                ;
        #ifdef SPIS_SLAVE_SEL_EN                ;
                                                ;
        movlw   024h                            ;
                                                ;
        #else                                   ;
                                                ;
        movlw   025h                            ;
                                                ;
        #endif                                  ;
                                                ;
        movwf   SSPCON1                         ;
        clrf    SSPBUF                          ;
                                                ;
        BANKSEL _vSPISIntTxBufWrPtr             ;
        clrf    _vSPISIntTxBufWrPtr             ;
        clrf    _vSPISIntTxBufRdPtr             ;
        clrf    _vSPISIntRxBufWrPtr             ;
        clrf    _vSPISIntRxBufRdPtr             ;
                                                ;
        clrf    vSPISIntStatus                  ;
        bsf     vSPISIntStatus,SPISSave         ;
        bsf     vSPISIntStatus,SPISTxBufEmpty   ;
        bsf     vSPISIntStatus,SPISRxBufEmpty   ;
                                                ;
        bsf     PIE1,SSPIE                      ;
        bsf     INTCON,PEIE                     ;
        bsf     INTCON,GIE                      ;
                                                ;
        return                                  ;
                                                ;
;***********************************************;




;***********************************************************************;
; Function: SPISIntISR                                                  ;
;                                                                       ;
; PreCondition: This has to be called from Interrupt handler            ;
;                                                                       ;
; Overview:                                                             ;
;       This is a interrupt service routine for Serial interrupt.       ;
;       It handles Reception and Transmission of data on interrupt.     ;
;       Call it from interrupt service routine.                         ;
;                                                                       ;
; Input: None                                                           ;
;                                                                       ;
; Output:                                                               ;
;    If data is received it puts it in vSPISIntBuffer and accordingly   ;
;    adjusts the vSPISIntBufWrPtr and clears SPISIntBufEmpty flag.      ;
;    If Buffer becomes full then it will set SPISIntBufFull flag.       ;
;    If data is received when buffer was full it will set SPISBufOF     ;
;    flag to indicate that transmitted data has been missed because     ;
;    of full Buffer. It will set ErrDataNotRcvd flag.                   ;
;                                                                       ;
;    If last data is transmitted then it will transmit next pending     ;
;    data if any. It will accordingly adjust the _vSPIIntBufRdPtr       ;
;    and clears the SPIIntBufFull flag. Which indicates that space      ;
;    is available for data in vSPISIntBuffer.                           ;
;                                                                       ;
; Side Effects: None                                                    ;
;                                                                       ;
; Stack requirement: 2 level deep                                       ;
;                                                                       ;
;***********************************************;***********************;
                                                ;
SPISIntISR:                                     ;
        GLOBAL  SPISIntISR                      ;
                                                ;
        btfss   PIR1,SSPIF                      ;check which interrupt has occurred sspif or bclif
        return                                  ;
                                                ;
        movf    SSPCON1,w                       ;
        andlw   00eh                            ;
        xorlw   004h                            ;
        btfss   STATUS,Z                        ;
        return                                  ;check is Slave Mode
                                                ;
;-----------------------------------------------;
                                                ;
        #if SPIS_RX_BUF_LENGTH == 0             ;
                                                ;
        movf    SSPBUF,W                        ;
                                                ;
        #else                                   ;
                                                ;
        #if SPIS_RX_BUF_LENGTH == 1             ;
                                                ;
;;        btfss   vSPISIntStatus,SPISRxBufFull    ;
                                                ;
        movff   SSPBUF,vSPISIntRxBuffer         ;
                                                ;
        #else                                   ;
                                                ;
        movff   SSPBUF,_vSPISIntTempReg         ;
                                                ;
        #endif                                  ;
        #endif                                  ;
                                                ;
        #if SPIS_TX_BUF_LENGTH == 0             ;
                                                ;
        clrf   SSPBUF                           ;
                                                ;
        #else                                   ;
                                                ;
        #if SPIS_TX_BUF_LENGTH == 1             ;
                                                ;
        movff   vSPISIntTxBuffer,SSPBUF         ;
                                                ;
        bcf     vSPISIntStatus,SPISTxBufFull    ;
        bsf     vSPISIntStatus,SPISTxBufEmpty   ;
                                                ;
        #else                                   ;
                                                ;
        movlw   000h                            ;
                                                ;
        btfss   vSPISIntStatus,SPISTxBufEmpty   ;
        call    _SPISIntRdTxBuf                 ;
                                                ;
        movwf   SSPBUF                          ;
                                                ;
        #endif                                  ;
        #endif                                  ;
                                                ;
        bcf     PIR1,SSPIF                      ;
                                                ;
        #if SPIS_RX_BUF_LENGTH != 0             ;
                                                ;
        btfsc   vSPISIntStatus,SPISRxBufFull    ;checking is buffer empty
        goto    SPISRxBfFlEr                    ;
                                                ;
        #if SPIS_RX_BUF_LENGTH == 1             ;
                                                ;
        bsf     vSPISIntStatus,SPISRxBufFull    ;
        bcf     vSPISIntStatus,SPISRxBufEmpty   ;
                                                ;
        #else                                   ;
                                                ;
        btfss   vSPISIntStatus,SPISSave         ;checking is buffer empty
        return                                  ;
                                                ;
        movff   _vSPISIntTempReg,WREG           ;
                                                ;
        call    _SPISIntWrRxBuf                 ;
                                                ;
        #endif                                  ;
                                                ;
        return                                  ;
                                                ;
SPISRxBfFlEr                                    ;
        bsf     vSPISIntStatus,SPISRxBufOverFlow;
                                                ;
        #endif                                  ;
                                                ;
        return                                  ;
                                                ;
;***********************************************;



        #if SPIS_TX_BUF_LENGTH != 0             ;
                                                ;
        #if SPIS_TX_BUF_LENGTH != 1             ;
                                                ;
;***********************************************************************;
; Function: _SPISIntRdTxBuf                                             ;
;                                                                       ;
; PreCondition: None.                                                   ;
;                                                                       ;
; Overview:                                                             ;
;       This reads data from buffer.                                    ;
;                                                                       ;
; Input: None                                                           ;
;                                                                       ;
; Output: 'W' Register                                                  ;
;                                                                       ;
; Side Effects: Bank selection bits and 'W' register are changed        ;
;                                                                       ;
; Stack requirement: 1 level deep                                       ;
;                                                                       ;
;***********************************************;***********************;
                                                ;
_SPISIntRdTxBuf:                                ;
                                                ;
        btfsc   vSPISIntStatus,SPISTxBufEmpty   ;
        return                                  ;
                                                ;
        movff   FSR0H,_vSPISIntDupFSRH          ;
        movff   FSR0L,_vSPISIntDupFSR           ;
                                                ;
        #ifdef  _DONT_USE_LFSR                  ;
                                                ;
        BANKSEL _vSPISIntTxBufRdPtr             ;
        movlw   HIGH(vSPISIntTxBuffer)          ;load wreg with read pointer address
        movwf   FSR0H                           ;
        movlw   LOW(vSPISIntTxBuffer)           ;
        addwf   _vSPISIntTxBufRdPtr,w           ;load fsr with read pointer address
        movwf   FSR0L                           ;
                                                ;
        #else                                   ;
                                                ;
        BANKSEL _vSPISIntTxBufRdPtr             ;
        lfsr    FSR0,vSPISIntTxBuffer           ;load fsr with read pointer address
        movf    _vSPISIntTxBufRdPtr,w           ;
        addwf   FSR0L                           ;
                                                ;
        #endif                                  ;
                                                ;
        btfsc   STATUS,C                        ;
        incf    FSR0H,f                         ;
                                                ;
        incf    _vSPISIntTxBufRdPtr,f           ;increment read pointer
        movlw   SPIS_TX_BUF_LENGTH              ;
        xorwf   _vSPISIntTxBufRdPtr,w           ;
        btfsc   STATUS,Z                        ;
        clrf    _vSPISIntTxBufRdPtr             ;
                                                ;
        movf    _vSPISIntTxBufRdPtr,w           ;Check is buffer empty
        xorwf   _vSPISIntTxBufWrPtr,w           ;
        btfsc   STATUS,Z                        ;
        bsf     vSPISIntStatus,SPISTxBufEmpty   ;
                                                ;
        movf    INDF0,w                         ;read the content of read pointer address
                                                ;
        movff   _vSPISIntDupFSR,FSR0L           ;
        movff   _vSPISIntDupFSRH,FSR0H          ;Retrive FSR
                                                ;
        bcf     vSPISIntStatus,SPISTxBufFull    ;
                                                ;
        return                                  ;
;***********************************************;

        #endif                                  ;
        #endif                                  ;
                                                ;


        #if SPIS_RX_BUF_LENGTH != 0             ;
                                                ;
        #if SPIS_RX_BUF_LENGTH != 1             ;
                                                ;
;***********************************************************************;
; Function: _SPISIntWrRxBuf                                             ;
;                                                                       ;
; PreCondition: None.                                                   ;
;                                                                       ;
; Overview:                                                             ;
;       This writes data into buffer.                                   ;
;                                                                       ;
; Input: 'W' Register                                                   ;
;                                                                       ;
; Output: None                                                          ;
;                                                                       ;
; Side Effects: Bank selection bits and 'W' register are changed        ;
;                                                                       ;
; Stack requirement: 1 level deep                                       ;
;                                                                       ;
;***********************************************;***********************;
                                                ;    
_SPISIntWrRxBuf:                                ;
        btfsc   vSPISIntStatus,SPISRxBufFull    ;
        return                                  ;
                                                ;
        movff   WREG,_vSPISIntTempReg           ;save the wreg content (data) in temflg
                                                ;
        movff   FSR0H,_vSPISIntDupFSRH          ;
        movff   FSR0L,_vSPISIntDupFSR           ;
                                                ;
        #ifdef  _DONT_USE_LFSR                  ;
                                                ;
        BANKSEL _vSPISIntRxBufWrPtr             ;
        movlw   HIGH(vSPISIntRxBuffer)          ;load wreg with read pointer address
        movwf   FSR0H                           ;
        movlw   LOW(vSPISIntRxBuffer)           ;load wreg with write pointer address
        addwf   _vSPISIntRxBufWrPtr,w           ;
        movwf   FSR0L                           ;load fsr with read pointer address
                                                ;
        #else                                   ;
                                                ;
        BANKSEL _vSPISIntRxBufWrPtr             ;
        lfsr    FSR0,vSPISIntRxBuffer           ;load fsr with read pointer address
        movf    _vSPISIntRxBufWrPtr,w           ;
        addwf   FSR0L                           ;
                                                ;
        #endif                                  ;
                                                ;
        btfsc   STATUS,C                        ;
        incf    FSR0H,f                         ;
                                                ;
        movff   _vSPISIntTempReg,INDF0          ;move tempreg content to write pointer pointing location
                                                ;
        movff   _vSPISIntDupFSR,FSR0L           ;
        movff   _vSPISIntDupFSRH,FSR0H          ;
                                                ;
        incf    _vSPISIntRxBufWrPtr,f           ;increment write pointer
        movlw   SPIS_RX_BUF_LENGTH              ;check for overflow of pointer
        xorwf   _vSPISIntRxBufWrPtr,w           ;
        btfsc   STATUS,Z                        ;
        clrf    _vSPISIntRxBufWrPtr             ;
                                                ;
        movf    _vSPISIntRxBufWrPtr,w           ;
        xorwf   _vSPISIntRxBufRdPtr,w           ;campare it with write pointer
        btfsc   STATUS,Z                        ;
        bsf     vSPISIntStatus,SPISRxBufFull    ;
                                                ;
        bcf     vSPISIntStatus,SPISRxBufEmpty   ;
                                                ;
        return                                  ;
                                                ;
;***********************************************;

        #endif                                  ;
        #endif                                  ;
                                                ;


        #if SPIS_TX_BUF_LENGTH != 0             ;
        #if SPIS_TX_BUF_LENGTH != 1             ;
                                                ;
;***********************************************************************;
; Function: _SPISIntWrTxBuf                                             ;
;                                                                       ;
; PreCondition: None.                                                   ;
;                                                                       ;
; Overview:                                                             ;
;       This writes data into buffer.                                   ;
;                                                                       ;
; Input: 'W' Register                                                   ;
;                                                                       ;
; Output: None                                                          ;
;                                                                       ;
; Side Effects: Bank selection bits and 'W' register are changed        ;
;                                                                       ;
; Stack requirement: 1 level deep                                       ;
;                                                                       ;
;***********************************************;***********************;
                                                ;    
_SPISIntWrTxBuf:                                ;
        GLOBAL  _SPISIntWrTxBuf                 ;
                                                ;
        btfsc   vSPISIntStatus,SPISTxBufFull    ;
        return                                  ;
                                                ;
        movff   WREG,_vSPISIntTempReg           ;save the wreg content (data) in temflg
                                                ;
        movff   FSR0H,_vSPISIntDupFSRH          ;
        movff   FSR0L,_vSPISIntDupFSR           ;
                                                ;
        #ifdef  _DONT_USE_LFSR                  ;
                                                ;
        BANKSEL _vSPISIntTxBufWrPtr             ;
        movlw   HIGH(vSPISIntTxBuffer)          ;load wreg with read pointer address
        movwf   FSR0H                           ;
        movlw   LOW(vSPISIntTxBuffer)           ;load wreg with write pointer address
        addwf   _vSPISIntTxBufWrPtr,w           ;
        movwf   FSR0L                           ;load fsr with read pointer address
                                                ;
        #else                                   ;
                                                ;
        BANKSEL _vSPISIntTxBufWrPtr             ;
        lfsr    FSR0,vSPISIntTxBuffer           ;load fsr with read pointer address
        movf    _vSPISIntTxBufWrPtr,w           ;
        addwf   FSR0L                           ;
                                                ;
        #endif                                  ;
                                                ;
        btfsc   STATUS,C                        ;
        incf    FSR0H,f                         ;
                                                ;
        movff   _vSPISIntTempReg,INDF0          ;move tempreg content to write pointer pointing location
                                                ;
        movff   _vSPISIntDupFSR,FSR0L           ;
        movff   _vSPISIntDupFSRH,FSR0H          ;
                                                ;
        incf    _vSPISIntTxBufWrPtr,f           ;increment write pointer
        movlw   SPIS_TX_BUF_LENGTH              ;check for overflow of pointer
        xorwf   _vSPISIntTxBufWrPtr,w           ;
        btfsc   STATUS,Z                        ;
        clrf    _vSPISIntTxBufWrPtr             ;
                                                ;
        movf    _vSPISIntTxBufWrPtr,w           ;
        xorwf   _vSPISIntTxBufRdPtr,w           ;campare it with write pointer
        btfsc   STATUS,Z                        ;
        bsf     vSPISIntStatus,SPISTxBufFull    ;
                                                ;
        bcf     vSPISIntStatus,SPISTxBufEmpty   ;
                                                ;
        return                                  ;
                                                ;
;***********************************************;

        #endif                                  ;
        #endif                                  ;
                                                ;


        #if SPIS_RX_BUF_LENGTH != 0             ;
        #if SPIS_RX_BUF_LENGTH != 1             ;
                                                ;
;***********************************************************************;
; Function: _SPISIntRdRxBuf                                             ;
;                                                                       ;
; PreCondition: None.                                                   ;
;                                                                       ;
; Overview:                                                             ;
;       This reads data from buffer.                                    ;
;                                                                       ;
; Input: None                                                           ;
;                                                                       ;
; Output: 'W' Register                                                  ;
;                                                                       ;
; Side Effects: Bank selection bits and 'W' register are changed        ;
;                                                                       ;
; Stack requirement: 1 level deep                                       ;
;                                                                       ;
;***********************************************;***********************;
                                                ;
_SPISIntRdRxBuf:                                ;
                                                ;
        GLOBAL  _SPISIntRdRxBuf                 ;
                                                ;
        btfsc   vSPISIntStatus,SPISRxBufEmpty   ;
        return                                  ;
                                                ;
        movff   FSR0H,_vSPISIntDupFSRH          ;
        movff   FSR0L,_vSPISIntDupFSR           ;
                                                ;
        #ifdef  _DONT_USE_LFSR                  ;
                                                ;
        BANKSEL _vSPISIntRxBufRdPtr             ;
        movlw   HIGH(vSPISIntRxBuffer)          ;load wreg with read pointer address
        movwf   FSR0H                           ;
        movlw   LOW(vSPISIntRxBuffer)           ;
        addwf   _vSPISIntRxBufRdPtr,w           ;load fsr with read pointer address
        movwf   FSR0L                           ;
                                                ;
        #else                                   ;
                                                ;
        BANKSEL _vSPISIntRxBufRdPtr             ;
        lfsr    FSR0,vSPISIntRxBuffer           ;load fsr with read pointer address
        movf    _vSPISIntRxBufRdPtr,w           ;
        addwf   FSR0L                           ;
                                                ;
        #endif                                  ;
                                                ;
        btfsc   STATUS,C                        ;
        incf    FSR0H,f                         ;
                                                ;
        incf    _vSPISIntRxBufRdPtr,f           ;increment read pointer
        movlw   SPIS_RX_BUF_LENGTH              ;
        xorwf   _vSPISIntRxBufRdPtr,w           ;
        btfsc   STATUS,Z                        ;
        clrf    _vSPISIntRxBufRdPtr             ;
                                                ;
        movf    _vSPISIntRxBufRdPtr,w           ;Check is buffer empty
        xorwf   _vSPISIntRxBufWrPtr,w           ;
        btfsc   STATUS,Z                        ;
        bsf     vSPISIntStatus,SPISRxBufEmpty   ;
                                                ;
        movf    INDF0,w                         ;read the content of read pointer address
                                                ;
        movff   _vSPISIntDupFSR,FSR0L           ;
        movff   _vSPISIntDupFSRH,FSR0H          ;Retrive FSR
                                                ;
        bcf     vSPISIntStatus,SPISRxBufFull    ;
                                                ;
        return                                  ;
;***********************************************;

        #endif                                  ;
        #endif                                  ;
                                                ;


        #if SPIS_RX_BUF_LENGTH != 0             ;
                                                ;
;***********************************************************************;
; Function: SPISIntDiscardRxBuf                                         ;
;                                                                       ;
; PreCondition: None.                                                   ;
;                                                                       ;
; Overview:                                                             ;
;       This flushes the buffer.                                        ;
;                                                                       ;
; Input: None                                                           ;
;                                                                       ;
; Output: None                                                          ;
;                                                                       ;
; Side Effects: None                                                    ;
;                                                                       ;
; Stack requirement: 1 level deep                                       ;
;                                                                       ;
;***********************************************;***********************;
                                                ;
SPISIntDiscardRxBuf:                            ;
        GLOBAL  SPISIntDiscardRxBuf             ;
                                                ;
        clrf    _vSPISIntRxBufRdPtr             ;
        clrf    _vSPISIntRxBufWrPtr             ;
        bsf     vSPISIntStatus,SPISRxBufEmpty   ;
        bcf     vSPISIntStatus,SPISRxBufFull    ;
                                                ;
        return                                  ;
                                                ;
;***********************************************;

        #endif                                  ;
                                                ;

;***********************************************;
;       END                                     ;
;***********************************************;

