'**************************************************************** '* Name : I2c_Slave_Asm.inc * '* Author : Pete Burnight * '* Notice : Copyright (c) 2007 Central Coast Software * '* : To be released under GNU Public License * '* Date : 3/3/07 * '* Version : 1.0 * '* Notes : * '* : * '**************************************************************** ASM I2C_INT ; Handle I2C (SSP) Interupt ; BCF STATUS, RP0 ; Bank 0 BCF PIR1, SSPIF ; Clear the interupt flag BSF _I2c_Flag, 0 ; Set Event Flag - something happened incf _I2c_Count,F BSF STATUS, RP0 ; Bank 1 movf SSPSTAT,W ; Get the value of SSPSTAT andlw 00101101b ; Mask out unimportant bits in SSPSTAT. BCF STATUS, RP0 ; Bank 0 movwf _I2c_Temp ; Put masked value in I2C_Temp ; -------------------------------------------------------------------------- ; State 1 - Master Write operation, ( Master Writes to us ) ; Last byte was an Address, so get ready for first data byte. ; Buffer is full. State1 movlw 00001001b xorwf _I2c_Temp,W btfss STATUS,Z ; Are we in State1? goto State2 ; No, check for next state..... ; Clrf _I2c_Rx_Index ; Clear the buffer index. movf SSPBUF,W ; Do a dummy read of SSPBuf to clear it GOTO ISR_Done ; -------------------------------------------------------------------------- ; State 2 - Master Write operation, ( Master Writes to us ) ; Last byte was Data, so this is more data. ; Buffer is full. State2 movlw 00101001b xorwf _I2c_Temp,W btfss STATUS,Z ; Are we in State 2? goto State3 ; No, check for next state..... movf SSPBUF,W ; Get the byte and put in WREG movwf _I2c_Byte ; --- save in buffer, inc index --- movlw _I2c_Rx_Buf ; Setup indirect addressing movwf FSR movf _I2c_Rx_Index,W addwf FSR,F movf _I2c_Byte,W movwf INDF ; put the byte into the buffer incf _I2c_Rx_Index,f ; inc the index movf _I2c_Rx_Index,W sublw I2C_BUFFERLEN ; subtract the buffer length btfsc STATUS,Z ; has index exceeded the buffer length? clrf _I2c_Rx_Index ; Yes, clear the Index GOTO ISR_Done ; -------------------------------------------------------------------------- ; State 3 - Master Read operation, ( Master reads from us ) ; Last byte was an address, so setup first data bytes. ; Buffer is empty. ; ; Fore-ground code always writes to front half of buffer ; Asm routine always reads from back half of buffer ; Check for new data & not busy - copy front to back State3 movlw 00001100b xorwf _I2c_Temp,W btfss STATUS,Z ; Are we in State 3? goto State4 ; No, check for next state..... btfss _I2c_DataFlag,1 ; Is there new data to copy? goto state3b ; if bit is set, skip this goto btfsc _I2c_DataFlag,0 ; Is table busy? Ok to Read? goto state3b ; if bit is clear, skip this goto ; Call CopyDblBuf bcf _I2c_DataFlag,1 ; clear new data flag state3b ; movlw I2C_DBLBUFLEN ; 8 bytes ; movwf _I2c_Tx_Index ; Setup to read back half of table clrf _I2c_Tx_Index movlw _I2c_Tx_Buf ; Setup indirect addressing movwf FSR movf _I2c_Tx_Index,W addwf FSR,F movf INDF,W ; Get the byte from the buffer Call WriteI2C ; Write the byte to SSPBUF incf _I2c_Tx_Index ; Inc the Index GOTO ISR_Done ; -------------------------------------------------------------------------- ; State 4 - Master Read operation, ( Master Reads data from us ) ; Last byte was data, so setup with more data. ; Buffer is empty. State4 movlw 00101100b xorwf _I2c_Temp,W btfss STATUS,Z ; Are we in State 4? goto State5 ; No, check for next state..... movf _I2c_Tx_Index,w ; get the Index sublw I2C_TXBUFLEN ; subtract the buffer len btfsc STATUS,Z ; Has the index exceeded the buffer length? CLRF _I2c_Tx_Index ; Yes, clear the buf index movlw _I2c_Tx_Buf ; Setup indirect addressing movwf FSR movf _I2c_Tx_Index,W addwf FSR,F movf INDF,W ; get byte from buffer Call WriteI2C ; write to SSPBUF incf _I2c_Tx_Index ; inc buf index GOTO ISR_Done ; -------------------------------------------------------------------------- ; State 5 - A NACK was received when transmitting data ; back from the master. Slave logic is reset in this case. ; R_W = 0, D_A = 1 and BF = 0 State5 movlw 00101000b xorwf _I2c_Temp,W btfss STATUS,Z ; Are we in State 5? goto I2c_Error ; No, error. bsf SSPCON,CKP ; Release the clock ? GOTO ISR_Done ; ---------------------- I2c_Error ; movlw 9 ; invalid state ; movwf _I2c_State GOTO ISR_Done ;--------------------------------------------------------------------- ; WriteI2C ;--------------------------------------------------------------------- ; SSPBUF = $13 ; SSPCON = $14 ; SSPSTAT = $94 - Bank1 WriteI2C BSF STATUS, RP0 ; Bank 1 btfsc SSPSTAT,BF ; Is the buffer full? goto WriteI2C ; Yes, keep waiting. BCF STATUS, RP0 ; No, continue. Bank 0 DoI2CWrite bcf SSPCON,WCOL ; Clear the WCOL flag. movwf SSPBUF ; Write the byte in WREG btfsc SSPCON,WCOL ; Was there a write collision? goto DoI2CWrite bsf SSPCON,CKP ; Release the clock. return EndASM ; -------------------------------------------------------------------------- ; Copy data from front 1/2 to back 1/2 of Double Buffer ASM CopyDblBuf BCF STATUS, RP0 ; Bank 0 movlw _I2c_Tx_Buf movwf _SrcPtr movlw I2C_DBLBUFLEN ; loop thru 8 bytes movwf _I2c_Tx_Index CopyLoop movf _SrcPtr,w movwf FSR movf INDF,w ; get byte from src movwf _I2c_Byte movlw I2C_DBLBUFLEN ; dist to dest = 8 bytes addwf FSR,f movf _I2c_Byte,w ; get byte from storage movwf INDF ; save in back half of Dbl Buf incf _SrcPtr decfsz _I2c_Tx_Index goto CopyLoop return EndASM ; End of Inc File