;;*****************************************************************************
;;*****************************************************************************
;;  FILENAME: I2CHWMSTR.asm
;;   Version: 1.90, Updated on 2012/3/2 at 9:14:43
;;  Generated by PSoC Designer 5.2.2551
;;
;;  DESCRIPTION: <UMName> User Module software implementation file
;;
;;  NOTE: User Module APIs conform to the fastcall16 convention for marshalling
;;        arguments and observe the associated "Registers are volatile" policy.
;;        This means it is the caller's responsibility to preserve any values
;;        in the X and A registers that are still needed after the API functions
;;        returns. For Large Memory Model devices it is also the caller's 
;;        responsibility to perserve any value in the CUR_PP, IDX_PP, MVR_PP and 
;;        MVW_PP registers. Even though some of these registers may not be modified
;;        now, there is no guarantee that will remain the case in future releases.
;;-----------------------------------------------------------------------------
;;  Copyright (c) Cypress Semiconductor 2012. All Rights Reserved.
;;*****************************************************************************
;;*****************************************************************************

include "m8c.inc"
include "memory.inc"
include "I2CHWCommon.inc"
include "I2CHWMstr.inc"

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

export   I2CHW_fSendRepeatStart
export  _I2CHW_fSendRepeatStart
export   I2CHW_fSendStart
export  _I2CHW_fSendStart
export   I2CHW_SendStop
export  _I2CHW_SendStop
; export the following 3 functions for C-implementations large or small mem models 
export  _I2CHW_fReadBytes
export  _I2CHW_bWriteBytes
export  _I2CHW_bWriteCBytes

export   I2CHW_fWrite
export  _I2CHW_fWrite

export   I2CHW_bRead
export  _I2CHW_bRead

export    I2CHW_bReadBusStatus
export   _I2CHW_bReadBusStatus


IF SYSTEM_SMALL_MEMORY_MODEL

export   I2CHW_fReadBytes
export   I2CHW_bWriteBytes
export   I2CHW_bWriteCBytes

ENDIF	 ;SYSTEM_SMALL_MEMORY_MODEL

;-------------------------------------------------------------------
;  Declare the varables for both the assembler and C compiler.
;
;-------------------------------------------------------------------
export  I2CHW_bStatus
export _I2CHW_bStatus

;-----------------------------------------------
; Variable Allocation
;-----------------------------------------------
area InterruptRAM(RAM, REL, CON)

_I2CHW_bStatus:
 I2CHW_bStatus:                        blk   1  ; Status during transfers

AREA UserModules (ROM, REL)
;-----------------------------------------------
;  EQUATES
;-----------------------------------------------
I2CHW_SLAVE_ACKed:                     equ 0x01 ; This bit set if Slave ACKed Master
I2CHW_SEND_ACK:                        equ 0x10 ; If this flag set, Master should send ACK


.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_fReadBytes
;
;  DESCRIPTION:
;       Read Multiple bytes from a slave.  Use the ISR to perform operation.
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;  [SP-7]=> Mode flags that allow the programmer to set flags
;           to determine if:
;             0x01 => Use RepeatStart instead of Start
;             0x02 => Don't send Stop
;  [SP-6]=> Count of bytes to read.
;  [SP-5]=> MSB of Array address to put data in (ignorned for small mem model)
;  [SP-4]=> LSB of Array address to put data in 
;  [SP-3]=> Address of slave
;
;  RETURNS:       None
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
;    Currently only the page pointer registers listed below are modified: 
;          CUR_PP
;
;  THEORY of OPERATION or PROCEDURE:
;    I2C and block must be operational.
;    This routine will enable the I2C interrupt!
;    If the I2CHW_ISR_ACTIVE indicates that the I2CHW_ISR is already running this routine will
;    pend on the ISR_ACTIVE bit until it can run
;
;-----------------------------------------------------------------------------
IF	(TOOLCHAIN & HITECH)
RxMode:         set  -7
RxCnt:          set  -6
RxArrayHI:      set  -5
RxArrayLO:      set  -4
RxSlaveAddr:    set  -3
ELSE
RxMode:         equ  -7
RxCnt:          equ  -6
RxArrayHI:      equ  -5
RxArrayLO:      equ  -4
RxSlaveAddr:    equ  -3
ENDIF

_I2CHW_fReadBytes:			      
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_PROLOGUE RAM_USE_CLASS_2
	RAM_SETPAGE_CUR >I2CHW_RsrcStatus
	mov   X, SP
I2CMSCR_NotReady1:
    mov    A, [I2CHW_RsrcStatus]                           ; test to see if previous command started ISR
    tst    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE
    ;mov   A, reg[I2CHW_MSCR]                              ;read the mscr register to look for pending master operations
    ;and   A, 0x0f                                           ;only look at the lower bits
          ;For multi master operations, a pening start or restart
          ;request might be OK, the master might be waiting to
          ;acquire the bus from another master
    jnz   I2CMSCR_NotReady1
    or    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE             ; flag set here and cleared by ISR
    ;get the address from the parameters on the stack
    mov   A, [X + RxSlaveAddr]
    asl   A                                                ; Shift address to the left to make
                                                           ; a complete byte with the R/W bit.
    or    A,0x01                                           ; OR the address with the Read bit.
    mov   [I2CHW_SlaveAddr], A                             ; preserve addr+r/w state for the ISR to use
    mov   reg[I2CHW_DR], A                                 ; put the write addr into the I2C_DR reg
    mov   [I2CHW_bStatus],0x00                             ; Clear all flags
    mov   A, [X+RxMode]                                    ; place the RxMode in status so ISR can access it
    mov   [I2CHW_bStatus],A
    ;
    ;we must now initialize a read buffer using I2CHW_InitWrite
    ;
    push   X                                               ;preserve since it's used later
    mov    A, [X+RxCnt]                                    ;get the write buf size
    push   A
    mov    A, [X+RxArrayHI]                                ;get the write addrHI
    push   A										   
    mov    A, [X+RxArrayLO]							                         ;get the write addrLO
    push   A                                               ;this will be ignored
    call  I2CHW_InitWrite                                  ;sets the addr and byte count to write to
    add    SP, -3
    pop    X                                               ;restore X to be used for the rest of this routine
    
    mov   A,[I2CHW_SlaveAddr]
    tst   [x+RxMode],I2CHW_RepStart
    jnz   DoRestartRx
    tst   reg[I2CHW_SCR], I2C_BYTE_COMPL                   ; indicates the I2C bus is stalled
    jnz   DoRestartRx
    call  I2C_DoStart                                      ; Send a start and address.
    jmp   CheckRxAck
DoRestartRx:
    call  I2CHW_DoBufferRepeatStart                           ; Send a repeat start and address.
        ;note that REPEATSTART can only be used if this master currently has control of the bus and is at the end
        ; of or ending the current data transmission/reception.  This also requres that the software (this UM)
        ; as a whole be able to detect that a stop has not been sent previously in this transmission.

CheckRxAck:                                                ; Test to see if Slave ACKed
        ;nothing to do here, a start and address are being transmitted, wait for the ISR to pick up, when it
        ;is finished.
End_RD:
    RAM_EPILOGUE RAM_USE_CLASS_2
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_bWriteBytes
;
;  DESCRIPTION:
;    Write multiple data bits to slave device.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
; [SP-7]=> Mode flags that allow the programmer to set flags
;          to determine if:
;              0x01 => Use RePeatStart instead of Start
;              0x02 => Don't send Stop
; [SP-6]=> Count of bytes to write.
; [SP-5]=> MSB of Array address to put data in (ignored small mem model).
; [SP-4]=> LSB of Array address to put data in.
; [SP-3]=> Address of slave
;
;
;  RETURNS:     None
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
;    Currently only the page pointer registers listed below are modified: 
;          CUR_PP
;
;  THEORY of OPERATION or PROCEDURE:
;
;-----------------------------------------------------------------------------
IF	(TOOLCHAIN & HITECH)
TxMode:       set  -7
TxByteCount:  set  -6
TxArrayHI:    set  -5
TxArrayLO:    set  -4
TxSlaveAddr:  set  -3
ELSE
TxMode:       equ  -7
TxByteCount:  equ  -6
TxArrayHI:    equ  -5
TxArrayLO:    equ  -4
TxSlaveAddr:  equ  -3
ENDIF

_I2CHW_bWriteBytes:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_PROLOGUE RAM_USE_CLASS_2
	RAM_SETPAGE_CUR >I2CHW_RsrcStatus

	mov   X, SP
I2CMSCR_NotReady2:
    mov    A, [I2CHW_RsrcStatus]                           ; test to see if previous command started ISR
    tst    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE
    ;mov   A, reg[I2CHW_MSCR]                              ;read the mscr register to look for pending master operations
    ;and   A, 0x0f                                           ;only look at the lower bits
          ;For multi master operations, a pening start or restart
          ;request might be OK, the master might be waiting to
          ;acquire the bus from another master
    jnz   I2CMSCR_NotReady2
    or    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE             ; flag set here and cleared at end of ISR
    mov   A, [X + TxSlaveAddr]
    asl   A                                                ; Shift address to the left to make
                                                           ; a complete byte with the R/W bit.
                                                           ; The ASL takes care of clearing bit 0.
    mov   [I2CHW_bStatus],0x00                             ; Clear all flags
    mov   [I2CHW_SlaveAddr], A                             ; preserve addr+r/w state for the ISR to use
    mov   reg[I2CHW_DR], A                                 ; put the write addr into the I2C_DR reg
    mov   A, [X+TxMode]                                    ; place the TxMode in status so ISR can access it
    mov   [I2CHW_bStatus],A
    ;
    ;we must now initialize a read buffer using I2CHW_InitWrite
    ;
        push   X                                                ;preserve since it's used later
        inc    [X+TxByteCount]                                 ;increase this by one since the init routine will decrement it by 1

        mov    A, [X+TxByteCount]                               ;get the write buf size
        push   A
        mov    A, [X+TxArrayHI]                                 ;get the write buf addr
        push   A                                                                                            ;this will be ignored
        mov    A, [X+TxArrayLO]                                 ;get the write buf addr
        push   A
        call  I2CHW_InitRamRead                            ;sets the addr and byte count to write to
        add SP, -3
        pop X                                                   ;restore X to be used for the rest of this routine
    ;and  [I2CHW_RsrcStatus],~I2C_READFLASH                ;shouldn't be needed should have been taken care of in InitRamRead routine


    mov   A,[I2CHW_SlaveAddr]
    tst   [x+TxMode],I2CHW_RepStart
    jnz   DoRestartTx
    tst   reg[I2CHW_SCR], I2C_BYTE_COMPL                   ; indicates the I2C bus is stalled
    jnz   DoRestartRx
    call  I2C_DoStart                                      ; Send a start and address.
    jmp   DoTxAck
DoRestartTx:
    call  I2CHW_DoBufferRepeatStart                           ; Send a repeat start and address.
DoTxAck:


WriteSlaveAck:
    RAM_EPILOGUE RAM_USE_CLASS_2
	RAM_EPILOGUE RAM_USE_CLASS_4
    ret

.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_bWriteCBytes
;
;  DESCRIPTION:
;    Write multiple data bits to slave device from ROM
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;  [SP-7]=> Mode flags that allow the programmer to set flags
;            to determine if:
;               0x01 => Use RepeatStart instead of Start
;               0x02 => Don't send Stop
;  [SP-6]=> Count of bytes to write.
;  [SP-5]=> MSB of ROM Array address to get data from
;  [SP-4]=> LSB of ROM Array address to get data from.
;  [SP-3]=> Address of slave
;
;  RETURNS:
;    None
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
;    Currently only the page pointer registers listed below are modified: 
;          CUR_PP
;
;  THEORY of OPERATION or PROCEDURE:
;
;-----------------------------------------------------------------------------
IF	(TOOLCHAIN & HITECH)
TxCMode:       set  -7
TxCByteCount:  set  -6
TxCArrayMSB:   set  -5
TxCArrayLSB:   set  -4
;TxSlaveAddr:  set  -3	  ;defined above this line if for reference only
ELSE
TxCMode:       equ  -7
TxCByteCount:  equ  -6
TxCArrayMSB:   equ  -5
TxCArrayLSB:   equ  -4
;TxSlaveAddr:  equ  -3	  ;defined above this line if for reference only
ENDIF

_I2CHW_bWriteCBytes:
    RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_PROLOGUE RAM_USE_CLASS_2
	RAM_SETPAGE_CUR >I2CHW_RsrcStatus
	mov   X, SP
I2CMSCR_NotReady3:
        mov    A, [I2CHW_RsrcStatus]                       ; test to see if previous command started ISR
        tst    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE
    ;mov   A, reg[I2CHW_MSCR]                              ;read the mscr register to look for pending master operations
    ;and   A, 0x0f                                           ;only look at the lower bits
          ;For multi master operations, a pening start or restart
          ;request might be OK, the master might be waiting to
          ;acquire the bus from another master
        jnz   I2CMSCR_NotReady3
        or    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE         ;lag set here but cleared in ISRf
    mov   A, [X + TxSlaveAddr]
    asl   A                                                ; Shift address to the left to make
                                                           ; a complete byte with the R/W bit.
                                                           ; The ASL takes care of clearing bit 0.
    mov   [I2CHW_bStatus],0x00                             ; Clear all flags
    mov   [I2CHW_SlaveAddr], A                             ; preserve addr+r/w state for the ISR to use
    mov   reg[I2CHW_DR], A                                 ; put the write addr into the I2C_DR reg
    mov   A, [X+TxCMode]                                                             ; place the RxMode in status so ISR can access it
    mov   [I2CHW_bStatus],A
    ;
        ;we must now initialize a read buffer using I2CHW_InitWrite
        ;
        push   X                                                ;preserve X since it's used later

         mov    A, 0                                             ;get the write buf size (this is the hi order part)
        inc    [X+TxCByteCount]                                 ;increase this by one since the init routine will decrement it by 1
        jnc    . + 3                                           ;but the ISR understands the original count passed (sigh...)(F.O.E.O.)
        inc    A                                                                                        ;if the low order part of the count happened to roll to 0x00, inc the hi part
        push   A
        mov    A, [X+TxCByteCount]                              ;initFlasRead needs a 2 byte count this is the low ord byte
        push   A
        mov    A, [X+TxCArrayMSB]                               ;get the write buf addr
        push   A                                                                                        ;this will be ignored
        mov    A, [X+TxCArrayLSB]                               ;get the write buf addr
        push   A

        call  I2CHW_InitFlashRead                          ;sets the addr and byte count to write to
        add SP, -4
        pop X                                                   ;restore X to be used for the rest of this routine

    ;or  [I2CHW_RsrcStatus],I2C_READFLASH
    mov   A,[I2CHW_SlaveAddr]
    tst   [x+TxMode],I2CHW_RepStart                        ; Check if a Start or RepeatStart
    jnz   DoCRestartTx                                     ; should executed.
    tst   reg[I2CHW_SCR], I2C_BYTE_COMPL                   ; indicates the I2C bus is stalled
    jnz   DoRestartRx
    call  I2C_DoStart                                      ; Send a start and address.
    jmp   DoCTxAck
DoCRestartTx:
    call  I2CHW_DoBufferRepeatStart                           ; Send a repeat start and address.

DoCTxAck:                                                  ; Test to see if Slave is ACKed

CWriteSlaveAck:
    RAM_EPILOGUE RAM_USE_CLASS_2
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_DoBufferRepeatStart
;
;  DESCRIPTION:
;    Send repeated start condition and send slave address for buffered transfers.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     This routine is called internally only.  It is not exported or intended as an API
;
;  RETURNS:
;    None
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
;  THEORY of OPERATION or PROCEDURE:
;    This is similar to the I2C_DoRepeatStart entry point but this function does not
;    wait for the byte_complete flag.  That is this is not polled and is therefore compatible
;    with the buffered read and write functions (above).
;
;-----------------------------------------------------------------------------

I2CHW_DoBufferRepeatStart:
    RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_SETPAGE_CUR >I2CHW_SlaveAddr
    ;here the path through the routine is dependent on the previous transmission.
        ; 1. a slave being written too must have acked or nakk'ed the previous byte (generating a Byte complete
        ; I2C interrupt
        ; 2a. the master must NAK the byte if he is reading from the slave.
        ; We do have to look at the status of the I2C block to see what is going on because if there was a
        ; previous write to a slave it may have ack'ed or nak'ed so we set an address and attempt a repeat start
        ; by setting the master restart bit and clearing to I2C_SCR (I2C_TX)
        ; 2b. if we are reading from theslave we would NAK it by clearing the I2C_ACKOUT bit and writing I2C_TX to the
        ; I2C_SCR reg.  (same as if we were writing to slave).
        ; 3. once the ISR starts it will figure out which direction we are going with data (sending/receiving)
        ;
    mov   reg[I2CHW_DR], A
        mov   [I2CHW_SlaveAddr], A
        ;tst      reg[I2CHW_MSCR], I2CM_MASTEROP           ;do we even have control of the bus?
        ;jz    notBusMasterErr
    mov   A, reg[I2CHW_MSCR]                               ;read the mscr register to look for pending master operations
    and   A, 0x0f                                          ;only look at the lower bits
        jz    BusIdleSendStart
        ; for a single master system this should not be an issue,
        ; so we'll go ahead and request the restart.  If a stop condition was already generated
        ; the state machine will automatically generate a start instead.

        ;SetI2CHW_SCR I2CM_RESTRT
    ;mov   reg[I2CHW_MSCR], I2CM_RESTRT
        ;SetI2CHW_SCR          I2C_TX                                ;even though the restart has been requested the state
        ;mov      reg[I2CHW_SCR], I2C_TX                   ;even though the restart has been requested the state

;IF I2CHW_THROTTLE_CLK_RATE
        SetI2CHW_MSCR I2CM_RESTRT
;ELSE
;    mov   reg[I2CHW_MSCR], I2CM_RESTRT
;ENDIF
    tst   reg[I2CHW_SCR], I2C_TX
    jnz   I2C_RestartRecieve

;IF I2CHW_THROTTLE_CLK_RATE
    SetI2CHW_SCR I2C_TX                                    ;even though the restart has been requested the state
;ELSE
;    mov   reg[I2CHW_SCR], I2C_TX                          ;send Ack
;ENDIF

    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
I2C_RestartRecieve:

;IF I2CHW_THROTTLE_CLK_RATE
    SetI2CHW_SCR 0                                         ;even though the restart has been requested the state
;ELSE
;    mov   reg[I2CHW_SCR], 0                               ;send Ack
;ENDIF

   RAM_EPILOGUE RAM_USE_CLASS_4
   ret

BusIdleSendStart:
   mov    A, [I2CHW_SlaveAddr]
   call   I2C_DoStart
   ;Since something appears to be messed up do the next best thing to a repeat start, send a start.
   RAM_EPILOGUE RAM_USE_CLASS_4
   ret

.ENDSECTION

.SECTION

;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_fSendRepeatStart
;
;  DESCRIPTION:
;    Send repeated start condition and send slave address.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;    I2CHW_bAddr - Contains the slave address and transfer direction.
;
;  RETURNS:
;    I2CHW_bSTatus - nonZero if a slave responds to a request. Zero otherwise
;    Acc register contains non zero value for success (contents of the i2C_SCR reg)  0 indicates failure
;    Returns a zero if the repeat start results in a NAK by an addressed device.
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
;    Currently only the page pointer registers listed below are modified: 
;          CUR_PP
;
;  THEORY of OPERATION or PROCEDURE:
;    Prepare to send start by setting SCl and SDA high.
;    must be followed directly by I2CHW_start.
;
;-----------------------------------------------------------------------------
 I2CHW_fSendRepeatStart:
_I2CHW_fSendRepeatStart:
    RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_SETPAGE_CUR >I2CHW_bStatus
    ;wait if the bus is already busy...
    push  A
    mov   [I2CHW_bStatus], 0x00
I2CMSCR_NotReady4:
    mov    A, [I2CHW_RsrcStatus]                           ; test to see if previous command started ISR
    tst    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE
    ;mov   A, reg[I2CHW_MSCR]                              ;read the mscr register to look for pending master operations
    ;and   A, 0x0f                                           ;only look at the lower bits
          ;For multi master operations, a pening start or restart
          ;request might be OK, the master might be waiting to
          ;acquire the bus from another master
    jnz   I2CMSCR_NotReady4
    pop   A


    asl   a                                                ; Shift address to the left
    dec   x                                                ; If zero, C flag will be set
    jc    I2C_DoRepeatStart                                ; Do a write if zero
    or    a,0x01                                           ; Set Read flag

I2C_DoRepeatStart:
    ;here the path through the routine is dependent on the previous transmission.
        ; 1. a slave being written too must have acked or nakk'ed the previous byte (generating a Byte complete
        ; I2C interrupt
        ; 2. the master must NAK the byte if he is reading from the slave.
        ; We don't have to look at the status of the I2C block to see what is going on because if there was a
        ; previous write to a slave it may have ack'ed or nak'ed so we set an address and attempt a repeat start
        ; by setting the master restart bit and writing to I2C_SCR (I2C_TX)
        ; if we are reading from theslave we would NAK it by clearing the I2C_ACKOUT bit and writing I2C_TX to the
        ; I2C_SCR reg.  (same as if we were writing to slave).
        ;
    mov   reg[I2CHW_DR], A
    mov   [I2CHW_SlaveAddr], A
    tst       reg[I2CHW_MSCR], I2CM_MASTEROP               ;do we even have control of the bus?
    jz    notBusMaster1
    ;SetI2CHW_MSCR  I2CM_RESTRT
    ;mov   reg[I2CHW_MSCR], I2CM_RESTRT
    ;SetI2CHW_SCR         I2C_TX                           ;even though the restart has been requested the state
    ;mov      reg[I2CHW_SCR], I2C_TX                       ;even though the restart has been requested the state
                                                                ; machine is stalling the SCL and has to be 'released'
;IF I2CHW_THROTTLE_CLK_RATE
    SetI2CHW_MSCR I2CM_RESTRT
    SetI2CHW_SCR  0                                        ;getting a restart out requires a 0 into the SCR reg
;ELSE
;    mov   reg[I2CHW_MSCR], I2CM_RESTRT
;    mov   reg[I2CHW_SCR], 0                               ;getting a restart out requires a 0 into the SCR reg
;ENDIF

WaitRepStrtCompl:
    mov   A,  reg[I2CHW_SCR]
    tst   reg[I2CHW_SCR],I2C_BYTE_COMPL                    ; Test to see if Slave ACKed
    jz    WaitRepStrtCompl
    tst   reg[I2CHW_SCR], I2C_LST_BIT
    jnz   Err_Exit_RepStart
    mov   [I2CHW_bStatus], 0x01
    mov   A, 01
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

Err_Exit_RepStart:
    mov   A, 0
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

 notBusMaster1:
    ;SetI2CHW_MSCR 0
    ;mov reg[I2CHW_MSCR], 0                                ;we certainly cant restart if we've not Master
    ;WHAT else should be done for this case?  Some sort of improper operation is being attempted.
    mov   A, 0
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_fSendStart
;
;  DESCRIPTION:
;    Generates start condition and sends slave address.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;    A => Contains the slave address.
;
;  RETURNS:
;    I2CHW_bSTatus - nonZero if a slave responds to a request. Zero otherwise
;    Acc register contains non zero value for success (contents of the i2C_SCR reg)  0 indicates failure
;    Returns a zero if the repeat start results in a NAK by an addressed device.
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
;    Currently only the page pointer registers listed below are modified: 
;          CUR_PP
;
;  THEORY of OPERATION or PROCEDURE:
;   Send start by setting SDA low while SCL is high. Set
;   SCL low in preparation to send address. 
;   Sends address, waits for byte complete
;   An address must be followed by a read or write of data if it was acked by a slave
;
;  WARNING: this routine will disable the I2C interrupt.  It will wait until the I2C_BYTE_COMPLETE
;   flag is set to return.
;
;
;-----------------------------------------------------------------------------
 I2CHW_fSendStart:
_I2CHW_fSendStart:
    RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_SETPAGE_CUR >I2CHW_bStatus 
    ;wait if the bus is already busy...
    push  A
    mov   [I2CHW_bStatus], 0x00
I2CMSCR_NotReady5:
    mov    A, [I2CHW_RsrcStatus]                           ; test to see if previous command started ISR
    tst    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE
    ;mov   A, reg[I2CHW_MSCR]                              ;read the mscr register to look for pending master operations
    ;and   A, 0x0f                                           ;only look at the lower bits
          ;For multi master operations, a pening start or restart
          ;request might be OK, the master might be waiting to
          ;acquire the bus from another master
    jnz   I2CMSCR_NotReady5
    pop   A


    ; disable the interrupt
        ; *** NOT REENABLED ***
        ;
    M8C_DisableIntMask I2CHW_INT_REG, I2CHW_INT_MASK
    tst   reg[I2CHW_SCR],I2C_BYTE_COMPL                    ;If there is a pending BYTE_COMPL here
                                                                ;it is highly probable that a start is not the
                                                                                                                    ;correct thing to do.
                                                                                                                    ;leaving
    jnz   Err_Exit_Start

    asl   a                                                ; Shift address to the left
    dec   x                                                ; If zero, C flag will be set
    jc    I2C_SndWRStart                                   ; Do a write if zero
    or    a,0x01                                           ; Set Read flag
I2C_SndWRStart:
    mov   reg[I2CHW_DR], A
    mov   [I2CHW_SlaveAddr], A
    ;SetI2CHW_MSCR, I2CM_SNDSTRT
    ;mov   reg[I2CHW_MSCR], I2CM_SNDSTRT

;IF I2CHW_THROTTLE_CLK_RATE
    SetI2CHW_MSCR I2CM_SNDSTRT
;ELSE
;    mov   reg[I2CHW_MSCR], I2CM_SNDSTRT
;ENDIF


WaitStrtByteCompl:
    mov   A,  reg[I2CHW_SCR]
    tst   reg[I2CHW_SCR],I2C_BYTE_COMPL                    ; Test to see if Slave ACKed
    jz    WaitStrtByteCompl
    tst   reg[I2CHW_SCR], I2C_LST_BIT
    jnz   Err_Exit_Start
    mov   [I2CHW_bStatus], 0x01
    mov   A, 01
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
Err_Exit_Start:
    mov   A, 0
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

I2C_DoStart:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >I2CHW_SlaveAddr
    ;here we are not required to test for master operation since we are only attempting to gain control of the bus
    ; by attempting to assert a Start
    
    mov   reg[I2CHW_DR], A
    mov   [I2CHW_SlaveAddr], A
    ;SetI2CHW_MSCR  I2CM_SNDSTRT
    ;mov   reg[I2CHW_MSCR], I2CM_SNDSTRT

;IF I2CHW_THROTTLE_CLK_RATE
    SetI2CHW_MSCR I2CM_SNDSTRT
;ELSE
;    mov   reg[I2CHW_MSCR], I2CM_SNDSTRT
;ENDIF
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
;
;   DO NOT PLACE
;   .SECTION
;   .ENDSECTION
;   _fSendStart USES CODE BELOW
;
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_fWrite
;
;  DESCRIPTION:
;    Writes a byte to the I2C master bus.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;    A contains Data to be written to I2C slave.
;
;  RETURNS:
;    1 If ACKed, else 0
;
;  SIDE EFFECTS:
;    REGISTERS ARE VOLATILE: THE A AND X REGISTERS MAY BE MODIFIED!
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
;  FUNCTION NAME: I2CHW_fWrite
;
;  DESCRIPTION:
;    Writes a data byte to the I2C master bus. 
;
;  ARGUMENTS:
;    Reg A contains slave address.
;    I2CHW_bData - Contains data to be transmitted.
;
;  RETURNS:
;    I2CHW_bStatus - Cleared if a slave responds to a request. Set otherwise
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
;    Currently only the page pointer registers listed below are modified: 
;          CUR_PP
;
;    Send data byte to slave. .
;
;   WARNING: this routine will disable the I2C interrupt.  It will wait until the I2C_BYTE_COMPLETE
;    flag is set to return.
;
 I2CHW_fWrite:
_I2CHW_fWrite:
    RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_SETPAGE_CUR >I2CHW_bStatus
    ; disable the interrupt
        ; *** NOT REENABLED ***
        ;
    mov   reg[I2CHW_DR],A                                  ; Put data in Data Reg
    M8C_DisableIntMask I2CHW_INT_REG, I2CHW_INT_MASK
    mov   A,  reg[I2CHW_MSCR]                              ;MSCR into A incase there is an error here
    tst   reg[I2CHW_MSCR],I2CM_MASTEROP                    ;Do we have control of the bus?
    jz    Err_Exit_fWrite

    mov   [I2CHW_bStatus],0x00                             ; Clear ACK flag
    ;SetI2CHW_SCR I2C_TX
    ;mov   reg[I2CHW_SCR], I2C_TX                          ; Put data in Data Reg

;IF I2CHW_THROTTLE_CLK_RATE
        SetI2CHW_SCR I2C_TX                                ; Put data in Data Reg
;ELSE
;    mov   reg[I2CHW_SCR], I2C_TX                          ; Put data in Data Reg
;ENDIF


I2CHW_write:
_I2CHW_write:
;    mov   reg[I2CHW_SCR],A                                ; Put data in bData
;   jmp   I2CHW_get_ack                                    ; This jump is not required since it falls

WaitTXByteCompl:
    mov   A, reg[I2CHW_SCR]
    tst   reg[I2CHW_SCR],I2C_BYTE_COMPL                    ; Test to see if Slave ACKed
    jz    WaitTXByteCompl
    tst   reg[I2CHW_SCR], I2C_LST_BIT
    jnz   Err_Exit_fWrite
    mov   [I2CHW_bStatus], 0xff
    mov   A, 01
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

Err_Exit_fWrite:
    mov   A, 0
    mov   [I2CHW_bStatus], A
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_get_ack
;
;  DESCRIPTION:
;    Get slave acknowledge response. Used to poll for I2C_BYTE_COMPL and then test Ack (I2C_LST_BIT)
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;
;  RETURNS:
;    Sets flag in I2CHW_bStatus if ACKed by Slave.  !!!
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
;    Currently only the page pointer registers listed below are modified: 
;          CUR_PP
;
;    Do the ack clock and check for Slave ACK
;
I2CHW_get_ack:
_I2CHW_get_ack:
    RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_SETPAGE_CUR >I2CHW_bStatus
    and [I2CHW_bStatus], ~I2CHW_SLAVE_ACKed
    tst reg[I2CHW_SCR], I2C_BYTE_COMPL
    jnz I2CHW_get_ack
    tst reg[I2CHW_SCR], I2C_LST_BIT
    jnz notAcked
    or [I2CHW_bStatus], I2CHW_SLAVE_ACKed
notAcked:
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

.ENDSECTION

.SECTION

;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_bRead
;
;  DESCRIPTION:
;    Reads 1 data byte from the I2C master bus.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;    Reg A Contains the Slave Address.
;    I2CHW_bStatus - Set for no ack to be followed by stop.
;    Clear for ack to indicate more data to follow.
;
;  RETURNS:
;    I2CHW_bData - Contains received data.
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
;    Currently only the page pointer registers listed below are modified: 
;          CUR_PP
;
;    Must be followed by I2CHW_put_ack.
;    The I2CHW interrupt should be disabled since this routine will poll the
;    reg[I2CHW_SCR] to determine when a byte is available
;
;   WARNING: this routine will disable the I2C interrupt.  It will wait until the I2C_BYTE_COMPLETE
;    flag is set to return.
;
I2CHW_bRead:
_I2CHW_bRead:
    RAM_PROLOGUE RAM_USE_CLASS_4
	RAM_SETPAGE_CUR >I2CHW_bStatus
    ; disable the interrupt
    ; *** NOT REENABLED ***
    ;
    M8C_DisableIntMask I2CHW_INT_REG, I2CHW_INT_MASK
    tst       reg[I2CHW_MSCR], I2CM_MASTEROP               ;do we even have control of the bus?
    jz    notBusMaster2

    mov   [I2CHW_bStatus],0x00                             ; Clear ACK flag
    ;or    I2CHW_SEND_ACK                                  ; Set ACK flag
;
; Check for the special case of the first read after and address is sent
;

    push  A                                                ;preserve the information about wether to ACK or NAK this byte
    mov   A, reg[I2CHW_SCR]
    tst   reg[I2CHW_SCR], I2C_ADDRIN
    jz    WaitRXByteCompl                                  ;addr bit not set then this is a normal read
    ;SetI2CHW_SCR 0
    ;mov   reg[I2CHW_SCR], 0                               ;clear the I2C_ADDR bit (to unstall SCL) & wait for next byte

;IF I2CHW_THROTTLE_CLK_RATE
    SetI2CHW_SCR 0                                         ;clear the I2C_ADDR bit (to unstall SCL) & wait for next byte
;ELSE
;    mov   reg[I2CHW_SCR], 0                               ;clear the I2C_ADDR bit (to unstall SCL) & wait for next byte
;ENDIF
                                                           ; through to I2CHW_put_ack.

    ;must DROP through to send an Ack and another byte,
    ;to stop reading we NAK the slave
WaitRXByteCompl:
    tst   reg[I2CHW_SCR],I2C_BYTE_COMPL                    ; Test to see if Slave ACKed
    jz    WaitRXByteCompl

    pop   A                                                ;recover the saved ACK/NAK flag
    and   A,0xFF                                           ; Is Ack flag set"
    jz    exit_bRead_NOACK                                 ; Don't ACK

        ;now if the ACK flag was set, Ack the data which will release the bus and start the next byte in
        ;otherwise do NOTHING to the SCR reg.  This will allow the calling routine to generate a repeat start
        ;or a stop depending on it's preference.


    mov   A, reg[I2CHW_DR]                                 ; Record data received
    ;SetI2CHW_SCR I2C_ACKOUT
    ;mov   reg[I2CHW_SCR], I2C_ACKOUT                      ; Record data received

;IF I2CHW_THROTTLE_CLK_RATE
    SetI2CHW_SCR I2C_ACKOUT                                ; Record data received
;ELSE
;    mov   reg[I2CHW_SCR], I2C_ACKOUT                      ; Record data received
;ENDIF

    mov   [I2CHW_bStatus],0x01                             ; Clear ACK flag
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

exit_bRead_NOACK:
    mov   A, reg[I2CHW_DR]                                 ; Record data received
    ; send no Ack or Nak, the calling routine will have to decide to NAK or execute a repeat start.
    ; sending nothing leaves the bus held in wait until a decision is made.
    mov   [I2CHW_bStatus],0x00                             ; Clear ACK flag
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

notBusMaster2:
   mov   [I2CHW_bStatus], 0xff
   ;SetI2CHW_SCR 0
   ;mov          reg[I2CHW_MSCR], 0                        ;we certainly cant restart if we've not Master
   ;WHAT else should be done for this case?  Some sort of improper operation is being attempted.
   RAM_EPILOGUE RAM_USE_CLASS_4
   ret

.ENDSECTION


.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_SendStop
;
;  DESCRIPTION:
;    Assert stop condition.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS: none
;
;  RETURNS: none
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;
;  THEORY of OPERATION or PROCEDURE:
;     Send stop by releasing SDA high while SCL high. When in Master Read Mode, this
;     is done by nak'ing a read from the slave, in Master Write Mode this is done by clearing
;     the I2C_TX bit in  reg[I2CHW_SCR].  In either case this is a zero written to
;     reg[I2CHW_SCR].
;
 I2CHW_SendStop:
_I2CHW_SendStop:
    RAM_PROLOGUE RAM_USE_CLASS_1
    tst   reg[I2CHW_MSCR], I2CM_MASTEROP                   ;do we even have control of the bus?
    jz    notBusMaster3
    ;SetI2CHW_SCR 0
    ;mov  reg[I2CHW_SCR], 0
;IF I2CHW_THROTTLE_CLK_RATE
    SetI2CHW_SCR 0                                         ; Put data in Data Reg
;ELSE
;    mov   reg[I2CHW_SCR], 0                               ; Put data in Data Reg
;ENDIF

notBusMaster3:
    RAM_EPILOGUE RAM_USE_CLASS_1
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_bReadBusStatus
;
;  DESCRIPTION:
;     Returns the Status bits in the bStatus Register
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;
;  RETURNS:
;     BYTE  bStatus -  Bus status data.  Use the following defined bits
;     returned in A.
;       I2CHW_RepStart:                     equ  0x01
;       I2CHW_NoStop:                       equ  0x02
;       I2CHW_NAKnextWr:                    equ  0x04
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
;  THEORY of OPERATION or PROCEDURE:
;     Read the Bus Status register.
;

 I2CHW_bReadBusStatus:
_I2CHW_bReadBusStatus:
   RAM_PROLOGUE RAM_USE_CLASS_4
   RAM_SETPAGE_CUR >I2CHW_bStatus				                      ;Set the Page Pointer for LMM
   mov   A, [I2CHW_bStatus]                      ;return the status in A
   RAM_EPILOGUE RAM_USE_CLASS_4
   ret

.ENDSECTION

IF SYSTEM_SMALL_MEMORY_MODEL
.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_fReadBytes
;
;  DESCRIPTION:
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;      A => Address of slave
;      X => Pointer to other arguments.
;    [x] => LSB of Array address to put data in.
;  [X-1] => MSB of Array address to put data in (ignorned)
;  [X-2] => Count of bytes to read.
;  [X-3] => Mode flags that allow the programmer to set flags
;           to determine if:
;             0x01 => Use RepeatStart instead of Start
;             0x02 => Don't send Stop
;
;  RETURNS:       None
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
;    Currently only the page pointer registers listed below are modified: 
;          CUR_PP
;
;  THEORY of OPERATION or PROCEDURE:
;    I2C and block must be operational.
;    This routine will enable the I2C interrupt!
;    If the I2CHW_ISR_ACTIVE indicates that the I2CHW_ISR is already running this routine will
;    pend on the ISR_ACTIVE bit until it can run
;
IF	(TOOLCHAIN & HITECH)
RxArray:      set   0
RxByteCount:  set  -2
RxMode:       set  -3
ELSE
RxArray:      equ   0
RxByteCount:  equ  -2
RxMode:       equ  -3
ENDIF


 I2CHW_fReadBytes:
    push  A
I2CMSCR_NotReady1Smm:
        mov    A, [I2CHW_RsrcStatus]                       ; test to see if previous command started ISR
        tst    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE
    ;mov   A, reg[I2CHW_MSCR]                              ;read the mscr register to look for pending master operations
    ;and   A, 0x0f                                           ;only look at the lower bits
          ;For multi master operations, a pening start or restart
          ;request might be OK, the master might be waiting to
          ;acquire the bus from another master
        jnz   I2CMSCR_NotReady1Smm
    pop   A
        or    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE         ; flag set here and cleared by ISR
    asl   A                                                ; Shift address to the left to make
                                                           ; a complete byte with the R/W bit.
    or    A,0x01                                           ; OR the address with the Read bit.
    mov   [I2CHW_SlaveAddr], A                             ; preserve addr+r/w state for the ISR to use
    mov   reg[I2CHW_DR], A                                 ; put the write addr into the I2C_DR reg
    mov   [I2CHW_bStatus],0x00                             ; Clear all flags
    mov   A, [X+RxMode]                                                             ; place the RxMode in status so ISR can access it
    mov   [I2CHW_bStatus],A
    ;
        ;we must now initialize a read buffer using I2CHW_InitWrite
        ;
        push   X                                                ;preserve since it's used later
        mov    A, [X+RxByteCount]                               ;get the write buf size
        push   A
        push   A                                                                                            ;this will be ignored
        mov    A, [X+RxArray]                                   ;get the write buf addr
        push   A
        mov    X, sp
        dec    X
        call  I2CHW_InitWrite                              ;sets the addr and byte count to write to
        add SP, -3
        pop X                                                   ;restore X to be used for the rest of this routine

    mov   A,[I2CHW_SlaveAddr]
    tst   [x+RxMode],I2CHW_RepStart
    jnz   DoRestartRxSmm
    tst   reg[I2CHW_SCR], I2C_BYTE_COMPL                   ; indicates the I2C bus is stalled
    jnz   DoRestartRxSmm
    call  I2C_DoStart                                      ; Send a start and address.
    jmp   CheckRxAckSmm
DoRestartRxSmm:
    call  I2CHW_DoBufferRepeatStart                           ; Send a repeat start and address.
        ;note that REPEATSTART can only be used if this master currently has control of the bus and is at the end
        ; of or ending the current data transmission/reception.  This also requres that the software (this UM)
        ; as a whole be able to detect that a stop has not been sent previously in this transmission.

CheckRxAckSmm:                                                ; Test to see if Slave ACKed
        ;nothing to do here, a start and address are being transmitted, wait for the ISR to pick up, when it
        ;is finished.
;End_RD:
    ret

.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_bWriteBytes
;
;  DESCRIPTION:
;    Write multiple data bits to slave device.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;     A => Address of slave
;     X => Pointer to other arguments.
;   [x] => LSB of Array address to put data in.
; [X-1] => MSB of Array address to put data in (ignorned)
; [X-2] => Count of bytes to write.
; [X-3] => Mode flags that allow the programmer to set flags
;          to determine if:
;              0x01 => Use RePeatStart instead of Start
;              0x02 => Don't send Stop
;
;
;  RETURNS:     None
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
IF	(TOOLCHAIN & HITECH)
TxArray:      set   0
TxByteCount:  set  -2
TxMode:       set  -3
ELSE
TxArray:      equ   0
TxByteCount:  equ  -2
TxMode:       equ  -3
ENDIF

 I2CHW_bWriteBytes:
    push  A
I2CMSCR_NotReady2Smm:
        mov    A, [I2CHW_RsrcStatus]                       ; test to see if previous command started ISR
        tst    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE
    ;mov   A, reg[I2CHW_MSCR]                              ;read the mscr register to look for pending master operations
    ;and   A, 0x0f                                           ;only look at the lower bits
          ;For multi master operations, a pening start or restart
          ;request might be OK, the master might be waiting to
          ;acquire the bus from another master
        jnz   I2CMSCR_NotReady2Smm
    pop   A
        or    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE         ; flag set here and cleared at end of ISR
    asl   A                                                ; Shift address to the left to make
                                                           ; a complete byte with the R/W bit.
                                                           ; The ASL takes care of clearing bit 0.
    mov   [I2CHW_bStatus],0x00                             ; Clear all flags
    mov   [I2CHW_SlaveAddr], A                             ; preserve addr+r/w state for the ISR to use
    mov   reg[I2CHW_DR], A                                 ; put the write addr into the I2C_DR reg
    mov   A, [X+TxMode]                                                             ; place the TxMode in status so ISR can access it
    mov   [I2CHW_bStatus],A
    ;
        ;we must now initialize a read buffer using I2CHW_InitWrite
        ;
        push   X                                                ;preserve since it's used later
        inc    [X+TxByteCount]                                 ;increase this by one since the init routine will decrement it by 1
                                                                ;but the ISR understands the original count passed (sigh...)(F.O.E.O.)
        mov    A, [X+TxByteCount]                               ;get the write buf size
        push   A
        push   A                                                                                            ;this will be ignored
        mov    A, [X+TxArray]                                   ;get the write buf addr
        push   A
        mov    X, sp
        dec    X
        call  I2CHW_InitRamRead                            ;sets the addr and byte count to write to
        add    SP, -3
        pop    X                                                ;restore X to be used for the rest of this routine
    ;and  [I2CHW_RsrcStatus],~I2C_READFLASH                ;shouldn't be needed should have been taken care of in InitRamRead routine


    mov   A,[I2CHW_SlaveAddr]
    tst   [x+TxMode],I2CHW_RepStart
    jnz   DoRestartTxSmm
    tst   reg[I2CHW_SCR], I2C_BYTE_COMPL                   ; indicates the I2C bus is stalled
    jnz   DoRestartRxSmm
    call  I2C_DoStart                                      ; Send a start and address.
    jmp   DoTxAckSmm
DoRestartTxSmm:
    call  I2CHW_DoBufferRepeatStart                           ; Send a repeat start and address.
DoTxAckSmm:


;WriteSlaveAck:
    ret

.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2CHW_bWriteCBytes
;
;  DESCRIPTION:
;    Write multiple data bits to slave device from ROM
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;      A => Address of slave
;      X => Pointer to other arguments.
;     [x] => LSB of ROM Array address to put data in.
;   [X-1] => MSB of ROM Array address to put data in (ignorned)
;   [X-2] => Count of bytes to write.
;   [X-3] => Mode flags that allow the programmer to set flags
;            to determine if:
;               0x01 => Use RepeatStart instead of Start
;               0x02 => Don't send Stop
;
;  RETURNS:
;    None
;
;  SIDE EFFECTS:
;    The A and X registers may be modified by this or future implementations
;    of this function.  The same is true for all RAM page pointer registers in
;    the Large Memory Model.  When necessary, it is the calling function's
;    responsibility to perserve their values across calls to fastcall16 
;    functions.
;          
IF	(TOOLCHAIN & HITECH)
TxCArrayLSB:   set   0
TxCArrayMSB:   set  -1
TxCByteCount:  set  -2
TxCMode:       set  -3
ELSE
TxCArrayLSB:   equ   0
TxCArrayMSB:   equ  -1
TxCByteCount:  equ  -2
TxCMode:       equ  -3
ENDIF

 I2CHW_bWriteCBytes:
    push  A
I2CMSCR_NotReady3Smm:
        mov    A, [I2CHW_RsrcStatus]                       ; test to see if previous command started ISR
        tst    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE
    ;mov   A, reg[I2CHW_MSCR]                              ;read the mscr register to look for pending master operations
    ;and   A, 0x0f                                           ;only look at the lower bits
          ;For multi master operations, a pening start or restart
          ;request might be OK, the master might be waiting to
          ;acquire the bus from another master
        jnz   I2CMSCR_NotReady3Smm
    pop   A
        or    [I2CHW_RsrcStatus], I2CHW_ISR_ACTIVE         ;lag set here but cleared in ISRf
        asl   A                                                 ; Shift address to the left to make
                                                           ; a complete byte with the R/W bit.
                                                           ; The ASL takes care of clearing bit 0.
    mov   [I2CHW_bStatus],0x00                             ; Clear all flags
    mov   [I2CHW_SlaveAddr], A                             ; preserve addr+r/w state for the ISR to use
    mov   reg[I2CHW_DR], A                                 ; put the write addr into the I2C_DR reg
        mov   A, [X+RxMode]                                                             ; place the RxMode in status so ISR can access it
    mov   [I2CHW_bStatus],A
    ;
        ;we must now initialize a read buffer using I2CHW_InitWrite
        ;
        push   X                                                ;preserve X since it's used later
        mov    A, 0                                             ;get the write buf size (this is the hi order part)
        inc    [X+TxCByteCount]                                 ;increase this by one since the init routine will decrement it by 1
        jnc     . + 3                                           ;but the ISR understands the original count passed (sigh...)(F.O.E.O.)
        inc    A                                                                                        ;if the low order part of the count happened to roll to 0x00, inc the hi part
        push   A
        mov    A, [X+TxCByteCount]                              ;initFlasRead needs a 2 byte count this is the low ord byte
        push   A
        mov    A, [X+TxCArrayMSB]                               ;get the write buf addr
        push   A                                                                                        ;this will be ignored
        mov    A, [X+TxCArrayLSB]                               ;get the write buf addr
        push   A
        mov    X, sp
        dec    X
        call  I2CHW_InitFlashRead                          ;sets the addr and byte count to write to
        add SP, -4
        pop X                                                   ;restore X to be used for the rest of this routine
    ;or  [I2CHW_RsrcStatus],I2C_READFLASH
    mov   A,[I2CHW_SlaveAddr]
    tst   [x+TxMode],I2CHW_RepStart                        ; Check if a Start or RepeatStart
    jnz   DoCRestartTxSmm                                      ; should executed.
    tst   reg[I2CHW_SCR], I2C_BYTE_COMPL                   ; indicates the I2C bus is stalled
    jnz   DoRestartRxSmm
    call  I2C_DoStart                                      ; Send a start and address.
    jmp   DoCTxAckSmm
DoCRestartTxSmm:
    call  I2CHW_DoBufferRepeatStart                           ; Send a repeat start and address.

DoCTxAckSmm:                                                   ; Test to see if Slave is ACKed

;CWriteSlaveAck:
        ret

.ENDSECTION


ENDIF	 ;SYSTEM_SMALL_MEMORY_MODEL

; End of File I2CHW.asm


