;;*****************************************************************************
;;*****************************************************************************
;;  FILENAME: I2CHW_1INT.asm
;;   Version: 1.4, Updated on 2004/12/22 at 15:01:22
;;  Generated by PSoC Designer ver 4.2  b1013 : 02 September, 2004
;;
;;  DESCRIPTION: UMName Interrupt Service Routine
;;  This is the interrupt seveice routine for the Single Master I2C function.
;;-----------------------------------------------------------------------------
;;  Copyright (c) Cypress MicroSystems 2004. All Rights Reserved.
;;*****************************************************************************
;;*****************************************************************************

include "m8c.inc"
include "memory.inc"
include "I2CHW_1Common.inc"
include "I2CHW_1Mstr.inc"

;-----------------------------------------------
;  Global Symbols
;-----------------------------------------------

export     I2CHW_1_Read_Count
export    _I2CHW_1_Read_Count
export     I2CHW_1_Write_Count
export    _I2CHW_1_Write_Count

export    pI2CHW_1_Read_BufLO
export   _pI2CHW_1_Read_BufLO
export    pI2CHW_1_Write_BufLO
export   _pI2CHW_1_Write_BufLO
export    I2CHW_1_RsrcStatus
export   _I2CHW_1_RsrcStatus
export    I2CHW_1_SlaveAddr
export   _I2CHW_1_SlaveAddr

;-----------------------------------------------
; WARNING: The variables below are deprecated
; and have been replaced with Read_BufLO
; and Write_BufLO
;-----------------------------------------------
export    pI2CHW_1_Read_Buf
export   _pI2CHW_1_Read_Buf
export    pI2CHW_1_Write_Buf
export   _pI2CHW_1_Write_Buf
;-----------------------------------------------
; END WARNING
;-----------------------------------------------
 
area InterruptRAM(RAM, REL, CON)

;-----------------------------------------------
; Variable Allocation
;-----------------------------------------------

  I2CHW_1_SlaveAddr:
 _I2CHW_1_SlaveAddr:                         blk      1
  I2CHW_1_RsrcStatus:
 _I2CHW_1_RsrcStatus:                        blk     1
  I2CHW_1_Write_Count:
 _I2CHW_1_Write_Count:                       blk    1
IF SYSTEM_LARGE_MEMORY_MODEL
export    pI2CHW_1_Write_BufHI
export   _pI2CHW_1_Write_BufHI

 pI2CHW_1_Write_BufHI:
_pI2CHW_1_Write_BufHI:                       blk     1
ENDIF
;-----------------------------------------------
; WARNING: The variable below is deprecated
; and has been replaced Write_BufLO
;-----------------------------------------------
 pI2CHW_1_Write_Buf:
_pI2CHW_1_Write_Buf:
;-----------------------------------------------
; END WARNING
;-----------------------------------------------
 pI2CHW_1_Write_BufLO:
_pI2CHW_1_Write_BufLO:                       blk      1

IF I2CHW_1_READ_FLASH
export    pI2CHW_1_Read_BufHI
export   _pI2CHW_1_Read_BufHI

 pI2CHW_1_Read_BufHI:
_pI2CHW_1_Read_BufHI:                        blk     1
ELSE
IF SYSTEM_LARGE_MEMORY_MODEL
export    pI2CHW_1_Read_BufHI
export   _pI2CHW_1_Read_BufHI

 pI2CHW_1_Read_BufHI:
_pI2CHW_1_Read_BufHI:                        blk     1
ENDIF
ENDIF

;-----------------------------------------------
; WARNING: The variable below is deprecated
; and has been replaced Read_BufLO
;-----------------------------------------------
 pI2CHW_1_Read_Buf:
_pI2CHW_1_Read_Buf:
;-----------------------------------------------
; END WARNING
;-----------------------------------------------
 pI2CHW_1_Read_BufLO:
_pI2CHW_1_Read_BufLO:                        blk       1

IF I2CHW_1_READ_FLASH
export    I2CHW_1_Read_CountHI
export   _I2CHW_1_Read_CountHI

 I2CHW_1_Read_CountHI:
_I2CHW_1_Read_CountHI:                       blk    1
ENDIF

 I2CHW_1_Read_Count:
_I2CHW_1_Read_Count:                         blk      1

;@PSoC_UserCode_INIT@ (Do not change this line.)
;---------------------------------------------------
; Insert your custom declarations below this banner
;---------------------------------------------------

;------------------------
; Includes
;------------------------

	
;------------------------
;  Constant Definitions
;------------------------


;------------------------
; Variable Allocation
;------------------------


;---------------------------------------------------
; Insert your custom declarations above this banner
;---------------------------------------------------
;@PSoC_UserCode_END@ (Do not change this line.)



AREA UserModules (ROM, REL)


export _I2CHW_1_ISR
;;****************************************************
;; I2C_MASTER  main entry point from vector 60h
;;
;;****************************************************


_I2CHW_1_ISR:
    push A
    push X
IF SYSTEM_LARGE_MEMORY_MODEL
    REG_PRESERVE IDX_PP
ENDIF
;;==============================================================
;* Master only
    ;here we shouldn't have to worry about arbitration, and not much about bus errors.
    ;On the other hand there's no way to tell the difference between Single Master mode
    ; and multi-Master mode.  So when Master mode is set, we may or may not need to do
    ; arbitration.  This could be an equate in the User Module possibly.
;;==============================================================

    ;
    ; stop trap is not recommendede becaus the stop bit cannot be cleared.  User may choose to enable
        ; it however
        ; Add code to handle stop condition here
        ;
    tst reg[I2CHW_1_SCR], I2C_ADDRIN
    jz DataState
    ;test for a start condition sent out, or bus error, ack from slave, or (lost arb & addr)
AddrState:
    tst reg[I2CHW_1_MSCR], I2CM_SNDSTRT
    jnz NoStart
    tst reg[I2CHW_1_SCR], ( I2C_LST_BIT )                  ;must be a zero or no slave answered
    jnz SlaveAddrNAK
                                                           ;slave must have acked here
                                                           ;here there needs to be some external state maintained by the Master that tells the
                                                           ;isr to transmit or to receive since it is in control.

    tst [I2CHW_1_SlaveAddr], 01                            ;bit 0 = 1 then read (from slave and put it in RAM,
                                                           ;bit 0 = 0 then write to slave and get it from RAM or Flash
    jnz I2C_ReadSlave1stByte                               ;bit 0 was 1


    jmp I2C_WriteSlave1stByte                              ;bit 0 was 0
IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
    reti


DataState:
        or [I2CHW_1_RsrcStatus], I2CHW_ISR_ACTIVE
    tst [I2CHW_1_SlaveAddr], 01                            ;bit 0 = 1 then read, bit 0 = 0 then write
    jnz I2C_ReadSlave                                      ;bit 0 was 1

    ;test the [I2CHW_1_Write_Count] for a value of zero meaning were done and we shouldn't transmit another byte
    ;merely return without doing anything, the foreground will generate a stop and figure out what
    ;to do next

        ;;
    ;;the buffer routine take care of deciding about how many bytes are left so I don't need to worry about it here
    ;;
StillDataToWrite:
    jmp I2C_WriteSlave                                     ;bit 0 was 0
IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
    reti


SlaveAddrNAK:
    ;;
    ;; all there is to do here is to return, the slave didn't respond so it's not there or needs
        ;; to be tried later.
    ;;
;
;;  CONTROL MACRO- writes to the SCR register and accounts for clock speed adjustments if necessary
;
    SetI2CHW_1_SCR 0     ;sets the tx/rx bit to receive, generates a stop without sending any data


    and [I2CHW_1_RsrcStatus], ~I2CHW_ISR_ACTIVE

IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
    reti

NoStart:
    ;here might test loss of arbitration and the presence of an address bit indicating that the
    ;Master is being addressed as a slave.
        ;;
        ;; there may be a need to indicate that there was a Master transmission
        ;; failure or an unsuccessful attempt...
        ;;
        and [I2CHW_1_RsrcStatus], ~I2CHW_ISR_ACTIVE
IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
    reti

I2C_ReadSlave1stByte:
        or [I2CHW_1_RsrcStatus], I2CHW_ISR_ACTIVE
        and [I2CHW_1_RsrcStatus], ~I2CHW_RD_COMPLETE

;read normal data in from slave immediately after the address is sent, there is no data to read
;but the bus is stalled at byte complete

;
;;  CONTROL MACRO- writes to the SCR register and accounts for clock speed adjustments if necessary
;
    SetI2CHW_1_SCR 0     ;sets the tx/rx bit to receive, and clocks a byte in


IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
    reti

I2C_ReadSlave:                                             ;this is just a normal read


;;code snipped from old SW I2C below
;
; MASTER READ from SLAVE
; (and writing to it's own RAM--Write_Buf and Write_Cnt)
;
;@PSoC_UserCode_BODY1_V1.2@ (Do not change this line.)
;---------------------------------------------------
; Insert your custom code below this banner
;---------------------------------------------------

;********************************************************
; By modifying the section from here down to the next comment block
; a user could process data for a custom I2C Master Read (write to RAM) application
; NOTE: I2C handshakes (ACK/NAK may be effected by any introduced bugs)
;********************************************************
   tst   [I2CHW_1_bStatus], fI2C_NAKnextWr
   jnz   InStoreData
   ;
   ;process write data here
   ;
   dec   [I2CHW_1_Write_Count]
   jc    CompleteRDXfer                                              ; carry set if value became -1
   ;jz    InStoreData                                                                                             ;In theory overflow cant happen but stop the transaction anyway.
   cmp   [I2CHW_1_Write_Count], 00                                   ;set nak flag, dec count, and store data
   jz    InNakNextByte
   jmp   InNotBufEnd
InNakNextByte:                                                       ;set the nakflag in I2CHW_1_bStatus
   or    [I2CHW_1_bStatus], fI2C_NAKnextWr
   jmp   InStoreData
InNotBufEnd:
   and   [I2CHW_1_bStatus], ~fI2C_NAKnextWr                          ;clear the nak flag in case it was set from a previous operation
InStoreData:
   ;This is the ONLY place this bit is set  This bit should never be cleared by the isr ONLY by the API ClrWrStatus()
   or    [I2CHW_1_RsrcStatus], I2CHW_WR_NOERR                        ;set current status
IF SYSTEM_LARGE_MEMORY_MODEL
   mov   A, [pI2CHW_1_Write_BufHI]
ENDIF
   RAM_SETPAGE_IDX A
   mov   X, [pI2CHW_1_Write_BufLO]
   mov   A, reg[I2CHW_1_DR]
   mov   [X],A                                                       ;save the laste byte
   inc   [pI2CHW_1_Write_BufLO]

   tst   [I2CHW_1_bStatus], fI2C_NAKnextWr
   jnz   NAK_this_one

;********************************************************
; End user I2C Buffered WRITE (to RAM) Customization
;********************************************************
;@PSoC_UserCode_END@ (Do not change this line.)
;;code snipped form SW I2C to maintain api compatibility above

;
;;  CONTROL MACRO- writes to the SCR register and accounts for clock speed adjustments if necessary
;
    SetI2CHW_1_SCR I2C_ACKOUT                                        ;send Ack


IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
    reti

NAK_this_one:

    and  [I2CHW_1_bStatus], ~fI2C_NAKnextWr

        ; *****
        ; here we may need to look at the mode that this was called under
        ; what does the user want done on the last byte.  Could be a send restart...
        ; ******
    and   [I2CHW_1_RsrcStatus], ~0x07                                ;clear the read status bits
    or    [I2CHW_1_RsrcStatus], I2CHW_RD_NOERR
    or    [I2CHW_1_RsrcStatus], I2CHW_RD_COMPLETE

        and [I2CHW_1_bStatus], (I2CHW_1_RepStart | I2CHW_1_NoStop)
        jz      CompleteRDXfer
        and   [I2CHW_1_RsrcStatus], ~I2CHW_ISR_ACTIVE
IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
        reti
        ;if neither a repeat start or a NoStop, then this must be a CompleteXfer request.
        ;The NAK (not I2C_SNDACK) bit in I2C_SCR below will automatically generate a stop

CompleteRDXfer:

;
;;  CONTROL MACRO- writes to the SCR register and accounts for clock speed adjustments if necessary
;
    SetI2CHW_1_SCR 0                                                 ;send Ack


    and   [I2CHW_1_RsrcStatus], ~I2CHW_ISR_ACTIVE
IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
    reti                                                             ;return and wait for the next interrupt (on data)


AckTheRead:

;
;;  CONTROL MACRO- writes to the SCR register and accounts for clock speed adjustments if necessary
;
    SetI2CHW_1_SCR I2C_ACKOUT                                        ;send Ack

IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
    reti


I2C_WriteSlave1stByte:
;write normal data to slave
        and [I2CHW_1_RsrcStatus], ~I2CHW_WR_COMPLETE
        or [I2CHW_1_RsrcStatus], I2CHW_ISR_ACTIVE


I2C_WriteSlave:

    tst reg[I2CHW_1_SCR], ( I2C_LST_BIT )                  ;must be a zero or no slave answered
    jnz SlaveDataNAK
        mov A, (I2C_TX)
        push A



;
;MASTER is WRITING TO SLAVE (& reading data from ram or flash buffer)
;
;;code snipped from SW I2C below

I2C_ObtainOutData:


;********************************************************
; here we need to get the next data to output (master-read)
; also set the status byte for use on exit
;********************************************************
IF I2CHW_1_READ_FLASH
;@PSoC_UserCode_BODY2_V1.2@ (Do not change this line.)
;---------------------------------------------------
; Insert your custom code below this banner
; to modify the way a master might read non-volitile data
; to send.
;---------------------------------------------------

    tst  [I2CHW_1_RsrcStatus],I2CHW_READFLASH
    jz   ReadOutData

    ;
    ;get the data
    ;
    mov  X, [pI2CHW_1_Read_BufLO]
    mov  A, [pI2CHW_1_Read_BufHI]
    romx
    mov  reg[I2CHW_1_DR],A
    dec  [I2CHW_1_Read_Count]                                        ;calc addr lsb
    jnc  NoDecHighCount
    dec  [I2CHW_1_Read_CountHI]

    jc   MstrWRComplete

NoDecHighCount:

    inc  [pI2CHW_1_Read_BufLO]                                       ;set the next flash address to read
    jnc  NoIncHiAddr
    inc  [pI2CHW_1_Read_BufHI]
NoIncHiAddr:
   jmp   I2CNormalOutput
;
;****** THERE SHOULD BE NO WAY TO REACH THIS STATE WE'LL JUST TERMINATE THE ACTIVITY SINCE WERE THE MASTER
;********    MAY LEAVE IT IN TO DEAL WITH MULTI MASTER SLAVE CONFIGS THOUGH BUT NOT IN THIS FILE
;
;FlashRdOverflow:
    ;deal with the over flow cond by resending last data byte (dec the low addr)

;   or    [I2CHW_1_RsrcStatus], I2CHW_RD_OVERFLOW
;                                                                      ;set count back to 0
;   mov   [I2CHW_1_Read_CountHI], 0                                  ;functionally the same as incrementing ffff and less instructions
;   mov   [I2CHW_1_Read_Count], 0
;   jmp   I2CNormalRead

;---------------------------------------------------
; Insert your custom code above this banner
;---------------------------------------------------
;@PSoC_UserCode_END@ (Do not change this line.)

ENDIF
;@PSoC_UserCode_BODY3@ (Do not change this line.)
;---------------------------------------------------
; Insert your custom code below this banner
; to modify the way a master might read RAM data to send
; to an I2C device
; By replacing the section from here down to the next block
; a user could process data for a custom I2C READ application
;---------------------------------------------------
ReadOutData:
   ;read the current data byte
IF SYSTEM_LARGE_MEMORY_MODEL
   mov   A, [pI2CHW_1_Read_BufHI]
ENDIF
   RAM_SETPAGE_IDX A
   mov   X, [pI2CHW_1_Read_BufLO]
   mov   A, [X]
   mov   reg[I2CHW_1_DR], A
   dec   [I2CHW_1_Read_Count]

   jc    MstrWRComplete
   inc   [pI2CHW_1_Read_BufLO]
   jmp   I2CNormalOutput
;
;ram read overflow detected here, just resend the last location in the buffer
;
;********        THERE SHOULD BE NO WAY TO OVERFLOW FOR THIS CASE
;********    MAY LEAVE IT IN TO DEAL WITH MULTI MASTER SLAVE CONFIGS THOUGH BUT NOT IN THIS FILE
;
;RamRDOverflow:
;   or    [I2CHW_1_RsrcStatus], I2CHW_RD_OVERFLOW
;   inc   [I2CHW_1_Read_Count]                                       ; set back to zero

;---------------------------------------------------
; End user I2C MASTER WRITE TO SLAVE /READ buffer customization section
; Insert your custom code above this banner
;---------------------------------------------------
;@PSoC_UserCode_END@ (Do not change this line.)
;;code snipped form SW I2C to maintain api compatibility above
I2CNormalOutput:

        ;load the bits to set in the I2C_ISR from the stack, The proper bit pattern was previously determined
        ;and place there based on whether or not the previous transmission was our I2C address.
        pop   A

;
;;  CONTROL MACRO- writes to the SCR register and accounts for clock speed adjustments if necessary
;
    SetI2CHW_1_SCR A                                                 ;Sets the I2C_TX bit in the I2C_SCR reg.


IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
    reti ;return and wait for the next interrupt (on data)

MstrWRComplete:
   and   [I2CHW_1_RsrcStatus], ~0x70                                 ;clear the write status bits
   or    [I2CHW_1_RsrcStatus], I2CHW_WR_COMPLETE
   or    [I2CHW_1_RsrcStatus], I2CHW_WR_NOERR
   mov   A, I2CHW_1_XFER_COMPLETE



        ; *****
        ; here we may need to look at the mode that this was called under
        ; what does the user want done on the last byte.  Could be a send restart...
        ; ******
        and [I2CHW_1_bStatus], (I2CHW_1_RepStart | I2CHW_1_NoStop)
        jz      CompleteWRXfer
        pop  A                                                            ;clear the stack for return
        and  [I2CHW_1_RsrcStatus], ~I2CHW_ISR_ACTIVE

IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
    reti
        ;if neither a repeat start or a NoStop, then this must be a CompleteXfer request.
        ; The release of the I2C_TX bit in I2C_SCR below will automatically generate a stop

CompleteWRXfer:

   pop   A

;
;;  CONTROL MACRO- writes to the SCR register and accounts for clock speed adjustments if necessary
;
    SetI2CHW_1_SCR 0                                                 ;this will release the bus and generate a stop condition

   and  [I2CHW_1_RsrcStatus], ~I2CHW_ISR_ACTIVE
IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
   pop X
   pop A
   reti

SlaveDataNAK:
;must also fix up the data buffer.  While it is marginally safe to nak a byte as a slave and 
;store it.  It is NEVER safe as a master to notice that a written byte has been nak'ed by a 
;slave and fail to resend it.
;this piece of code fixes up the count and buffer that the master is using to get data from
;to re-transmit the byte when the next master write is done.
    inc  [I2CHW_1_Read_Count]                          ;calc addr lsb
IF I2CHW_1_READ_FLASH
    jnc  NoIncHighCount
    inc  [I2CHW_1_Read_CountHI]

NoIncHighCount:
ENDIF
    dec  [pI2CHW_1_Read_BufLO]                         ;set the next flash address to read
IF SYSTEM_LARGE_MEMORY_MODEL
    jnc  NoDecHiAddr
    dec  [pI2CHW_1_Read_BufHI]
NoDecHiAddr:
ELSE
IF I2CHW_1_READ_FLASH
    jnc  NoDecHiCAddr
    dec  [pI2CHW_1_Read_BufHI]
NoDecHiCAddr:
ENDIF
ENDIF

    ;;
    ;; all there is to do here is to return & set status, the slave didn't want any more data
    ;;
        ;no pop needed because the nak is detected before the push happens above

;
;;  CONTROL MACRO- writes to the SCR register and accounts for clock speed adjustments if necessary
;
    SetI2CHW_1_SCR 0                                                 ;this will release the bus and generate a stop condition



        and [I2CHW_1_RsrcStatus], ~I2CHW_ISR_ACTIVE
    and   [I2CHW_1_RsrcStatus], ~0x70                                ;clear the write status bits
    or    [I2CHW_1_RsrcStatus], I2CHW_WR_COMPLETE
    or    [I2CHW_1_RsrcStatus], I2CHW_WR_OVERFLOW
IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
   reti

STOPTRAP:
    ;
    ;   If interrupt on STOP condition is enabled:
    ;   Add user code to process stop (not recommended becuase I2C bus is NOT stalled and ISR
        ;   may block reception of ongoing transactions/addresses
        ;   STOP condition is never detected when a repeat start is used by the master.
        ;
    and [I2CHW_1_RsrcStatus], ~I2CHW_ISR_ACTIVE
IF SYSTEM_LARGE_MEMORY_MODEL
    REG_RESTORE IDX_PP
ENDIF
    pop X
    pop A
    reti

; end of file I2CHW_1INT.asm
