;;*****************************************************************************
;;*****************************************************************************
;;  FILENAME: I2Cm_1.asm
;;   Version: 1.4, Updated on 2004/10/27 at 18:25:50
;;  Generated by PSoC Designer ver 4.2  b1013 : 02 September, 2004
;;
;;  DESCRIPTION: I2Cm User Module software implementation file for the
;;               22/24/25/26/27xxx PSoC family of devices.
;;
;;  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 MicroSystems 2000-2003. All Rights Reserved.
;;*****************************************************************************
;;*****************************************************************************

include "m8c.inc"
include "memory.inc"
include "I2Cm_1.inc"

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

export   I2Cm_1_Start
export  _I2Cm_1_Start
export   I2Cm_1_Stop
export  _I2Cm_1_Stop
export   I2Cm_1_fSendRepeatStart
export  _I2Cm_1_fSendRepeatStart
export   I2Cm_1_fSendStart
export  _I2Cm_1_fSendStart
export   I2Cm_1_SendStop
export  _I2Cm_1_SendStop
; export the following 3 functions for C-implementations large or small mem models 
export  _I2Cm_1_fReadBytes
export  _I2Cm_1_bWriteBytes
export  _I2Cm_1_bWriteCBytes

export   I2Cm_1_fWrite
export  _I2Cm_1_fWrite

export   I2Cm_1_bRead
export  _I2Cm_1_bRead

IF SYSTEM_SMALL_MEMORY_MODEL

export   I2Cm_1_fReadBytes
export   I2Cm_1_bWriteBytes
export   I2Cm_1_bWriteCBytes

ENDIF	 ;SYSTEM_SMALL_MEMORY_MODEL

;-------------------------------------------------------------------
;  Declare the varables for both the assembler and C compiler.
;
;-------------------------------------------------------------------
export  I2Cm_1_bStatus
export _I2Cm_1_bStatus
export  I2Cm_1_bData
export _I2Cm_1_bData
export  I2Cm_1_bAddr
export _I2Cm_1_bAddr

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

_I2Cm_1_bStatus:
 I2Cm_1_bStatus:                       blk   1  ; Status during transfers
_I2Cm_1_bData:
 I2Cm_1_bData:                         blk   1  ; Data transfered
_I2Cm_1_bXferCnt:
 I2Cm_1_bXferCnt:                                ; Reused variable for counting transfered
_I2Cm_1_bAddr:                                   ; Bytes
 I2Cm_1_bAddr:                         blk   1  ; Slave Address
_I2Cm_1_bit_count:
 I2Cm_1_bit_count:                     blk   1  ; Bit counter

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

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_Start
;
;  DESCRIPTION:
;
;-----------------------------------------------------------------------------
;
;  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.
;          
;    Currently only the page pointer registers listed below are modified: 
;          CUR_PP
;
;    Resets all pins on the I2C master port to the pulldown drive
;
;  THEORY of OPERATION or PROCEDURE:
;
;-----------------------------------------------------------------------------
 I2Cm_1_Start:
_I2Cm_1_Start:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >Port_1_DriveMode_1_SHADE
    ; Set pins to drive mode high Z
    or   [Port_1_DriveMode_1_SHADE],I2Cm_1_SDA_pin|I2Cm_1_SCL_pin
    and  [Port_1_DriveMode_0_SHADE],~(I2Cm_1_SDA_pin|I2Cm_1_SCL_pin)

    M8C_SetBank1                                     ; Setup port for normal operation
    mov  A,[Port_1_DriveMode_1_SHADE]
    mov  reg[I2Cm_1_I2CPRTDM1],A
    mov  A,[Port_1_DriveMode_0_SHADE]
    mov  reg[I2Cm_1_I2CPRTDM0],A
    M8C_SetBank0
                                                     ; Set both pins, low so that only the port
                                                     ; mode has to be changed from a 0 to a 1
    and  [Port_1_Data_SHADE],~(I2Cm_1_SDA_pin|I2Cm_1_SCL_pin)
    mov  A,[Port_1_Data_SHADE]
    mov  reg[I2Cm_1_I2CPRTDR],A
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_Stop
;
;  DESCRIPTION:
;    This function performs no operation and is used for future
;    module compatibility.
;
;-----------------------------------------------------------------------------
;
;  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.
;          
 I2Cm_1_Stop:
_I2Cm_1_Stop:
    RAM_PROLOGUE RAM_USE_CLASS_1
    RAM_EPILOGUE RAM_USE_CLASS_1
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_fReadBytes
;
;  DESCRIPTION:
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;  [SP-3]=> Address of slave
;  [SP-4]=> LSB of Array address to put data in.
;  [SP-5]=> MSB of Array address to put data in.
;  [SP-6]=> Count of bytes to read.
;  [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
;
;  RETURNS:
;    I2Cm_1_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
;		   IDX_PP
;
SlaveAdr:     equ  -3
RxArrayLSB:   equ  -4
RxArrayMSB:   equ  -5
RxByteCount:  equ  -6
RxMode:       equ  -7

_I2Cm_1_fReadBytes:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_PROLOGUE RAM_USE_CLASS_3
    RAM_SETPAGE_IDX2STK
    RAM_SETPAGE_CUR >I2Cm_1_bStatus
    mov   X, SP
    
    mov   A, [X+SlaveAdr]
    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   [I2Cm_1_bStatus],0x00                            ; Clear all flags
    tst   [x+RxMode],I2Cm_1_RepStart
    jnz   DoRestartRx
    call  I2C_DoStart                                      ; Send a start and address.
    jmp   CheckRxAck
DoRestartRx:
    call  I2C_DoRepeatStart                                ; Send a repeat start and address.
CheckRxAck:                                                ; Test to see if Slave ACKed
    RAM_SETPAGE_CUR >I2Cm_1_bStatus
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed
    jz    End_RD_Loop
                                                           ; Send ACK until last byte
    or    [I2Cm_1_bStatus],I2Cm_1_SEND_ACK                 ; Send ACK until last byte
RD_Loop:                                                   ; Loop through bytes
    push  x                                                ; Save X for later
    dec   [x+RxByteCount]                                  ; Decrement data counter
    jnz   I2C_READ
    and   [I2Cm_1_bStatus],~I2Cm_1_SEND_ACK                ; If last Byte, don't ACK
I2C_READ:
    call  I2Cm_1_read                                      ; Read a byte
    RAM_SETPAGE_CUR >I2Cm_1_bStatus
    pop   x                                                ; Restore x
    push  x
    mov   a,[x+RxArrayLSB]                                 ; Get pointer to data and put it in X
    push  a                                                ; push the index pointer onto the stack (will be popped to x) 
IF SYSTEM_LARGE_MEMORY_MODEL
    mov   A,[x+RxArrayMSB]
    RAM_SETPAGE_IDX A
ENDIF
    pop   x                                                ; restores the index pointer pushed a few lines above
    mov   a,[I2Cm_1_bData]                                 ; Save data in data array
    mov   [x],a                                            ; Put read data in array
    pop   x                                                ; Restore the original pointer (for the subrtn params)
    RAM_SETPAGE_IDX2STK					   ; Set Index Page to Stack Page
    inc   [x+RxArrayLSB]                                   ; Advance data pointer
    tst   [x+RxByteCount],FFh                              ; Decrement data counter
    jnz   RD_Loop                                          ; Not finished, do another byte.
End_RD_Loop:                                               ; Endloop
    tst   [x+RxMode],I2Cm_1_NoStop
    jnz   SkipRxStop
    call  I2Cm_1_SendStop
SkipRxStop:
    RAM_SETPAGE_CUR >I2Cm_1_bStatus
    mov   a,I2Cm_1_XFER_ERROR                              ; Clear return value until we test if slave ACKed
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed              ; Test to see if Slave ACKed
    jz    End_ReadBytes
    mov   a,I2Cm_1_XFER_COMPLETE                           ; Return ACKed True
End_ReadBytes:
    RAM_EPILOGUE RAM_USE_CLASS_3
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

IF SYSTEM_SMALL_MEMORY_MODEL
.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_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:
;    I2Cm_1_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.
;          
RxArray_X:      equ   0
RxByteCount_X:  equ  -2
RxMode_X:       equ  -3

 I2Cm_1_fReadBytes:		                 
    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   [I2Cm_1_bStatus],0x00                            ; Clear all flags
    tst   [x+RxMode_X],I2Cm_1_RepStart
    jnz   DoRestartRxSmm
    call  I2C_DoStart                                      ; Send a start and address.
    jmp   CheckRxAckSmm
DoRestartRxSmm:
    call  I2C_DoRepeatStart                                ; Send a repeat start and address.
CheckRxAckSmm:                                                ; Test to see if Slave ACKed
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed
    jz    End_RD_LoopSmm
                                                           ; Send ACK until last byte
    or    [I2Cm_1_bStatus],I2Cm_1_SEND_ACK                 ; Send ACK until last byte
RD_LoopSmm:                                                   ; Loop through bytes
    push  x                                                ; Save X for later
    dec   [x+RxByteCount_X]                                ; Decrement data counter
    jnz   I2C_READSmm
    and   [I2Cm_1_bStatus],~I2Cm_1_SEND_ACK                ; If last Byte, don't ACK
I2C_READSmm:
    call  I2Cm_1_read                                      ; Read a byte
    pop   x                                                ; Restore x
    push  x                                                ; Store x
    mov   x,[x+RxArray_X]                                  ; Get pointer to data and put it in X
    mov   a,[I2Cm_1_bData]                                 ; Save data in data array
    mov   [x+RxArray_X],a                                  ; Put read data in array
    pop   x                                                ; Restore the original pointer
    inc   [x+RxArray_X]                                    ; Advance data pointer
    tst   [x+RxByteCount_X],FFh                            ; Decrement data counter
    jnz   RD_LoopSmm                                       ; Not finished, do another byte.
End_RD_LoopSmm:                                            ; Endloop
    tst   [x+RxMode_X],I2Cm_1_NoStop
    jnz   SkipRxStopSmm
    call  I2Cm_1_SendStop
SkipRxStopSmm:
    mov   a,I2Cm_1_XFER_ERROR                              ; Clear return value until we test if slave ACKed
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed              ; Test to see if Slave ACKed
    jz    End_ReadBytesSmm
    mov   a,I2Cm_1_XFER_COMPLETE                           ; Return ACKed True
End_ReadBytesSmm:
    ret
.ENDSECTION
ENDIF

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_bWriteBytes
;
;  DESCRIPTION:
;    Write multiple data bits to slave device.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
; [SP-3] => Address of slave
; [SP-4] => LSB of Array address to put data in.
; [SP-5] => MSB of Array address to put data in.
; [SP-6] => Count of bytes to write.
; [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
;
;
;  RETURNS:
;    I2Cm_1_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
;		   IDX_PP
;
TxSlaveAdr:   equ  -3
TxArrayLSB:   equ  -4
TxArrayMSB:   equ  -5
TxByteCount:  equ  -6
TxMode:       equ  -7

_I2Cm_1_bWriteBytes:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_PROLOGUE RAM_USE_CLASS_3
    RAM_SETPAGE_IDX2STK
    RAM_SETPAGE_CUR >I2Cm_1_bStatus
    mov   X, SP
    
    mov   A,[x+TxSlaveAdr]
    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   [I2Cm_1_bStatus],0x00                       ; Clear all flags


    tst   [x+TxMode],I2Cm_1_RepStart
    jnz   DoRestartTx
    call  I2C_DoStart                                 ; Send a start and address.
    jmp   DoTxAck
DoRestartTx:
    call  I2C_DoRepeatStart                           ; Send a repeat start and address.
DoTxAck:
    RAM_SETPAGE_CUR >I2Cm_1_bStatus
    mov   [I2Cm_1_bXferCnt],0x00                      ; Zero out byte count first
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed         ; Test to see if Slave ACKed
    jz    End_WR_Loop
WR_Loop:                                              ; Loop through bytes
    RAM_SETPAGE_IDX2STK
    push  x                                           ; Save X for later
    mov   a,[x+TxArrayLSB]                            ; Get pointer to data and put it in X
	push  a                                           ; save the address on the stack (will pop it back into X)
IF SYSTEM_LARGE_MEMORY_MODEL
    mov   a,[x+TxArrayMSB]
    RAM_SETPAGE_IDX a                                 ; Set Index Page to pointer MSB
ENDIF
    pop   x                                           ; this recovers the address previously stoed on teh stack
    mov   a,[x]                                       ; Get data pointer to by X
    mov   [I2Cm_1_bData],a                            ; Save data in temp location
    call  I2Cm_1_write                                ; Write the data
	RAM_SETPAGE_CUR >I2Cm_1_bStatus
    RAM_SETPAGE_IDX2STK                               ; Set Index Page back to Stack Page   
    pop   x
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed
    jz    DoWBstop                                    ; Stop transfer if NAKed
    inc   [I2Cm_1_bXferCnt]                           ; Increment transfer byte count
    inc   [x+TxArrayLSB]                              ; Advance pointer
    dec   [x+TxByteCount]                             ; Decrement byte counter
    jnz   WR_Loop                                     ; Not finished, do another byte.
End_WR_Loop:                                          ; Endloop
    tst   [x+TxMode],I2Cm_1_NoStop
    jnz   SkipTxStop
DoWBstop:
    call  I2Cm_1_SendStop
SkipTxStop:
	RAM_SETPAGE_CUR >I2Cm_1_bStatus
    mov   a,[I2Cm_1_bXferCnt]                         ; Return bytes transfered
End_WriteBytes:
    RAM_EPILOGUE RAM_USE_CLASS_3
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION


IF SYSTEM_SMALL_MEMORY_MODEL
.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_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:
;    I2Cm_1_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.
;          
TxArray_X:      equ   0
TxByteCount_X:  equ  -2
TxMode_X:       equ  -3

 I2Cm_1_bWriteBytes:						       
    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   [I2Cm_1_bStatus],0x00                       ; Clear all flags


    tst   [x+TxMode_X],I2Cm_1_RepStart
    jnz   DoRestartTxSmm
    call  I2C_DoStart                                 ; Send a start and address.
    jmp   DoTxAckSmm
DoRestartTxSmm:
    call  I2C_DoRepeatStart                           ; Send a repeat start and address.
DoTxAckSmm:
    mov   [I2Cm_1_bXferCnt],0x00                      ; Zero out byte count first
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed         ; Test to see if Slave ACKed
    jz    End_WR_LoopSmm
WR_LoopSmm:                                              ; Loop through bytes
    push  x                                           ; Save X for later
    mov   x,[x+TxArray_X]                               ; Get pointer to data and put it in X
    mov   a,[x]                                       ; Get data pointer to by X
    mov   [I2Cm_1_bData],a                            ; Save data in temp location
    call  I2Cm_1_write                                ; Write the data
    pop   x
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed
    jz    DoWBstopSmm                                    ; Stop transfer if NAKed
    inc   [I2Cm_1_bXferCnt]                           ; Increment transfer byte count
    inc   [x+TxArray_X]                                 ; Advance pointer
    dec   [x+TxByteCount_X]                             ; Decrement byte counter
    jnz   WR_LoopSmm                                     ; Not finished, do another byte.
End_WR_LoopSmm:                                          ; Endloop
    tst   [x+TxMode_X],I2Cm_1_NoStop
    jnz   SkipTxStopSmm
DoWBstopSmm:
    call  I2Cm_1_SendStop
SkipTxStopSmm:
    mov   a,[I2Cm_1_bXferCnt]                         ; Return bytes transfered
End_WriteBytesSmm:
    ret
.ENDSECTION
ENDIF

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_bWriteCBytes
;
;  DESCRIPTION:
;    Write multiple data bits to slave device from ROM
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;   [SP-3] => Address of slave
;   [SP-4] => LSB of ROM Array address to put data in.
;   [SP-5] => MSB of ROM Array address to put data in (ignorned)
;   [SP-6] => Count of bytes to write.
;   [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
;
;  RETURNS:
;    I2Cm_1_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
;
TxCSlaveAdr:   equ  -3
TxCArrayLSB:   equ  -4
TxCArrayMSB:   equ  -5
TxCByteCount:  equ  -6
TxCMode:       equ  -7

_I2Cm_1_bWriteCBytes:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_PROLOGUE RAM_USE_CLASS_2
    RAM_SETPAGE_CUR >I2Cm_1_bStatus
    mov   X, SP

    mov   A,[x+TxCSlaveAdr]
    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   [I2Cm_1_bStatus],0x00                       ; Clear all flags


    tst   [x+TxCMode],I2Cm_1_RepStart                 ; Check if a Start or RepeatStart
    jnz   DoCRestartTx                                ; should executed.
    call  I2C_DoStart                                 ; Send a start and address.
    jmp   DoCTxAck
DoCRestartTx:
    call  I2C_DoRepeatStart                           ; Send a repeat start and address.

DoCTxAck:                                             ; Test to see if Slave is ACKed
	RAM_SETPAGE_CUR >I2Cm_1_bStatus
    mov   [I2Cm_1_bXferCnt],0x00            ; Zero out byte count first
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed
    jz    End_WRC_Loop
WRC_Loop:                                             ; Loop through bytes
    push  x                                           ; Save X for later

    mov   a,[x+TxCArrayMSB]                           ; Get data pointer to by X
    mov   x,[x+TxCArrayLSB]                           ; Get pointer to data and put it in X
    romx                                              ; Put ROM Data in a
    mov   [I2Cm_1_bData],a                            ; Save data in temp location
    call  I2Cm_1_write                                ; Write the data
    RAM_SETPAGE_CUR >I2Cm_1_bStatus
    pop   x
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed
    jz    DoWCBstop                                    ; Stop transfer if NAKed
    inc   [I2Cm_1_bXferCnt]                           ; Increment transfer byte count
    inc   [x+TxCArrayLSB]                             ; Advance LSB of pointer
    jnc   DecBCnt
    inc   [x+TxCArrayMSB]                             ; Advance MSB of pointer

DecBCnt:
    dec   [x+TxCByteCount]                            ; Decrement byte counter
    jnz   WRC_Loop                                    ; Not finished, do another byte.
End_WRC_Loop:                                         ; Endloop
    tst   [x+TxCMode],I2Cm_1_NoStop
    jnz   SkipTxCStop
DoWCBstop:
    call  I2Cm_1_SendStop
SkipTxCStop:
    RAM_SETPAGE_CUR >I2Cm_1_bStatus
    mov   a,[I2Cm_1_bXferCnt]                         ; Return bytes transfered
End_WriteCBytes:
    RAM_EPILOGUE RAM_USE_CLASS_2
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

IF SYSTEM_SMALL_MEMORY_MODEL
.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_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:
;    I2Cm_1_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.
;          
TxCArrayLSB_x:   equ   0
TxCArrayMSB_x:   equ  -1
TxCByteCount_x:  equ  -2
TxCMode_x:       equ  -3

 I2Cm_1_bWriteCBytes:					        
    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   [I2Cm_1_bStatus],0x00                       ; Clear all flags


    tst   [x+TxCMode_x],I2Cm_1_RepStart               ; Check if a Start or RepeatStart
    jnz   DoCRestartTxSmm                                ; should executed.
    call  I2C_DoStart                                 ; Send a start and address.
    jmp   DoCTxAckSmm
DoCRestartTxSmm:
    call  I2C_DoRepeatStart                           ; Send a repeat start and address.

DoCTxAckSmm:                                             ; Test to see if Slave is ACKed
    mov   [I2Cm_1_bXferCnt],0x00            ; Zero out byte count first
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed
    jz    End_WRC_LoopSmm
WRC_LoopSmm:                                             ; Loop through bytes
    push  x                                           ; Save X for later

    mov   a,[x+TxCArrayMSB_x]                           ; Get data pointer to by X
    mov   x,[x+TxCArrayLSB_x]                           ; Get pointer to data and put it in X
    romx                                              ; Put ROM Data in a
    mov   [I2Cm_1_bData],a                            ; Save data in temp location
    call  I2Cm_1_write                                ; Write the data
    pop   x
    tst   [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed
    jz    DoWCBstopSmm                                ; Stop transfer if NAKed
    inc   [I2Cm_1_bXferCnt]                           ; Increment transfer byte count
    inc   [x+TxCArrayLSB_x]                             ; Advance LSB of pointer
    jnc   DecBCntSmm
    inc   [x+TxCArrayMSB_x]                             ; Advance MSB of pointer

DecBCntSmm:
    dec   [x+TxCByteCount_x]                            ; Decrement byte counter
    jnz   WRC_LoopSmm                                    ; Not finished, do another byte.
End_WRC_LoopSmm:                                         ; Endloop
    tst   [x+TxCMode_x],I2Cm_1_NoStop
    jnz   SkipTxCStopSmm
DoWCBstopSmm:
    call  I2Cm_1_SendStop
SkipTxCStopSmm:
    mov   a,[I2Cm_1_bXferCnt]                         ; Return bytes transfered
End_WriteCBytesSmm:
    ret
.ENDSECTION
ENDIF

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_fSendRepeatStart
;
;  DESCRIPTION:
;    Send repeated start condition and send slave address.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;    I2Cm_1_bAddr - Contains the slave address and transfer direction.
;
;  RETURNS:
;    I2Cm_1_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
;
;  THEORY of OPERATION or PROCEDURE:
;    Prepare to send start by setting SCl and SDA high.
;    must be followed directly by I2Cm_1_start.
;
 I2Cm_1_fSendRepeatStart:
_I2Cm_1_fSendRepeatStart:
    RAM_PROLOGUE RAM_USE_CLASS_4
    asl   a                                                ; Shift address to the left
    dec   x                                                ; If zero, C flag will be set
    jnc   .setRead                                ; Do a write if zero
    call  I2C_DoRepeatStart
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.setRead:
    or    a,0x01                                           ; Set Read flag
    call  I2C_DoRepeatStart
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret  

I2C_DoRepeatStart:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >Port_1_DriveMode_0_SHADE
    push  a
    M8C_SetBank1
    or    [Port_1_DriveMode_0_SHADE],I2Cm_1_SCL_pin        ; Assert SCL low
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SDA_pin       ; Release SDA high
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

                                                           ; Delay 3/4 period
    mov   A,I2Cm_1_delay3qtr
    call  I2Cm_1_delay
                                                           ; Release SCL high
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SCL_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

    M8C_SetBank0
clockstretch1:                                             ; Wait for SCL high in case of wait
                                                           ; states adde by slave
    tst   reg[I2Cm_1_I2CPRTDR],I2Cm_1_SCL_pin
    jz    clockstretch1

    mov   A,I2Cm_1_delay3qtr                               ; Delay 1/2 period
    call  I2Cm_1_delay
    pop   a
    call  I2C_DoStart                                      ; Jump through to I2C_DoStart
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_fSendStart
;
;  DESCRIPTION:
;    Generates start condition and sends slave address.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;    A => Contains the slave address.
;
;  RETURNS:
;    I2Cm_1_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
;
;  THEORY of OPERATION or PROCEDURE:
;   Send start by setting SDA low while SCL is high. Set
;   SCL low in preparation to send address. Must be followed
;   by I2Cm_1_write.
;
 I2Cm_1_fSendStart:
_I2Cm_1_fSendStart:
    RAM_PROLOGUE RAM_USE_CLASS_4
    asl   a                                                     ; Shift address to the left
    dec   x                                                     ; If zero, C flag will be set
    jnc   .SetRead
    call  I2C_DoStart                                           ; Do a write if zero
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.SetRead:
    or    a,0x01                                                ; Set Read flag
    call  I2C_DoStart                                           ; Do a write if zero
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

I2C_DoStart:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >Port_1_DriveMode_0_SHADE
    M8C_SetBank1
    push  A                                                     ; Save the slave address
    or    [Port_1_DriveMode_0_SHADE],I2Cm_1_SDA_pin             ; Assert SDA low
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

    mov   A,I2Cm_1_delayhalf                                    ; Delay 1/2 period
    call  I2Cm_1_delay
    pop   A                                                     ; Restore slave address to A
    M8C_SetBank0
    RAM_SETPAGE_CUR >I2Cm_1_bData
    mov   [I2Cm_1_bData],A

    RAM_SETPAGE_CUR >Port_1_DriveMode_0_SHADE
    M8C_SetBank1
    or    [Port_1_DriveMode_0_SHADE],I2Cm_1_SCL_pin             ; Set SCL low
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A
    M8C_SetBank0

    mov   A,I2Cm_1_delayqtr                                     ; Delay 1/4 period
    call  I2Cm_1_delay
    call   I2Cm_1_write                                         ; Write the byte.
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_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: I2Cm_1_write
;
;  DESCRIPTION:
;    Writes a byte to the I2C master bus. Also used for sending the address.
;
;  ARGUMENTS:
;    Reg A contains slave address.
;    I2Cm_1_bData - Contains data to be transmitted.
;
;  RETURNS:
;    I2Cm_1_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. Must be followed by I2Cm_1_get_ack.
;
I2Cm_1_fWrite:
_I2Cm_1_fWrite:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >I2Cm_1_bData
    mov   [I2Cm_1_bData],A                                 ; Put data in bData
    call  I2Cm_1_write
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

I2Cm_1_write:
_I2Cm_1_write:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >I2Cm_1_bit_count
    
    mov   [I2Cm_1_bit_count],8                              ; Set up count to xmit 8 bits
writenextbit:
    dec   [I2Cm_1_bit_count]

    RAM_SETPAGE_CUR >Port_1_DriveMode_0_SHADE
                                                           ; Assert SCL low
    M8C_SetBank1
    or    [Port_1_DriveMode_0_SHADE],I2Cm_1_SCL_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A
    M8C_SetBank0

    RAM_SETPAGE_CUR >I2Cm_1_bit_count
    rlc   [I2Cm_1_bData]
    RAM_SETPAGE_CUR >Port_1_DriveMode_0_SHADE
    M8C_SetBank1
    jc    write_bit                                        ; Assert SDA low for data 0    
    or    [Port_1_DriveMode_0_SHADE],I2Cm_1_SDA_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

    jmp   writestartclock
write_bit:                                                 ; Release SDA high for data 1
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SDA_pin      
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

writestartclock:
    mov   A,I2Cm_1_delayhalf                               ; Delay 1/2 period
    call  I2Cm_1_delay
                                                           ; Release SCL High
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SCL_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

    M8C_SetBank0
clockstretch2:                                             ; Wait for SCL high in case of wait states
                                                           ; are added by slave.
    tst   reg[I2Cm_1_I2CPRTDR],I2Cm_1_SCL_pin
    jz    clockstretch2
                                                           ; Delay for 1/2 period
    mov   A,I2Cm_1_delayhalf
    call  I2Cm_1_delay

    RAM_SETPAGE_CUR >I2Cm_1_bit_count
    cmp   [I2Cm_1_bit_count],0
    jnz   writenextbit
    call  I2Cm_1_get_ack                

    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_get_ack
;
;  DESCRIPTION:
;    Get slave acknowledge response. Used only by I2Cm_1_write.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;    I2Cm_1_bData - Contains data to be transmitted.
;
;  RETURNS:
;    Sets flag in I2Cm_1_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
;
I2Cm_1_get_ack:
_I2Cm_1_get_ack:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >Port_1_DriveMode_0_SHADE
    M8C_SetBank1
    or    [Port_1_DriveMode_0_SHADE],I2Cm_1_SCL_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A
                                                           ; Release SDA high so slave may ACK
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SDA_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A
                                                           ; Delay 3/4 period
    mov   A,I2Cm_1_delay3qtr
    call  I2Cm_1_delay
                                                           ; Release SCL high
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SCL_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

    M8C_SetBank0
clockstretch3:                                             ; Wait for SCL to go high in case wait states
                                                           ; are added my slave.
    tst   reg[I2Cm_1_I2CPRTDR],I2Cm_1_SCL_pin
    jz    clockstretch3
    
    RAM_SETPAGE_CUR >I2Cm_1_bStatus    
                                                       ; Clear ACK bit
    and   [I2Cm_1_bStatus],~I2Cm_1_SLAVE_ACKed
    tst   reg[I2Cm_1_I2CPRTDR],I2Cm_1_SDA_pin
    jnz    getack2                                         ; If ACKed, set flag
    or    [I2Cm_1_bStatus],I2Cm_1_SLAVE_ACKed

getack2:
    mov   A,I2Cm_1_delayhalf                               ; Delay 1/2 period
    call  I2Cm_1_delay

    mov   A,[I2Cm_1_bStatus]                               ; Get result and put it in A
    and   A,I2Cm_1_SLAVE_ACKed                             ; Mask off just the ACK flag.
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_bRead
;
;  DESCRIPTION:
;    Reads 1 data byte from the I2C master bus.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;    Reg A Contains the Slave Address.
;    I2Cm_1_bStatus - Set for no ack to be followed by stop.
;    Clear for ack to indicate more data to follow.
;
;  RETURNS:
;    I2Cm_1_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 I2Cm_1_put_ack.
;
I2Cm_1_bRead:
_I2Cm_1_bRead:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >I2Cm_1_bStatus
    mov   [I2Cm_1_bStatus],0x00                            ; Clear ACK flag
    and   A,0xFF                                           ; Is Ack flag set"
    jz    I2Cm_1_read                                      ; Don't ACK
    or    [I2Cm_1_bStatus],I2Cm_1_SEND_ACK                 ; Set ACK flag
    call  I2Cm_1_read
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret

I2Cm_1_read:
_I2Cm_1_read:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >I2Cm_1_bStatus    
    mov   [I2Cm_1_bit_count],8                             ; Count and prepare bits to read
readnextbit:
    dec   [I2Cm_1_bit_count]
    rlc   [I2Cm_1_bData]
    
    RAM_SETPAGE_CUR >Port_1_DriveMode_0_SHADE
    M8C_SetBank1                                           ; Asser SCL low
    or    [Port_1_DriveMode_0_SHADE],I2Cm_1_SCL_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A
                                                           ; Delay 1/2 period
    mov   A,I2Cm_1_delayhalf
    call  I2Cm_1_delay
                                                           ; Release SCL high
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SCL_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

    M8C_SetBank0
    RAM_SETPAGE_CUR >I2Cm_1_bStatus    
clockstretch4:                                             ; Wait for SCL to go high in case slave
                                                           ; addes wait states.

    tst   reg[I2Cm_1_I2CPRTDR],I2Cm_1_SCL_pin
    jz    clockstretch4
                                                           ; Delay 1/4 period
    mov   A,I2Cm_1_delayqtr
    call  I2Cm_1_delay

    and   [I2Cm_1_bData],~01h                              ; Record bit received
    tst   reg[I2Cm_1_I2CPRTDR],I2Cm_1_SDA_pin
    jz    readnobit
    or    [I2Cm_1_bData],01h
readnobit:
    cmp   [I2Cm_1_bit_count],0
    jnz   readnextbit                                      ; Check for byte complete

    call   I2Cm_1_put_ack                
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION
                                                         
.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_put_ack
;
;  DESCRIPTION:
;    Send acknowledge to slave. Used only by I2Cm_1_read
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;    I2Cm_1_bStatus - Set for no ack to be followed by stop. Clear for ack
;    to indicate more data to follow.
;
;  RETURNS:
;    I2Cm_1_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
;
;    Send ack if more data will follow.
;
I2Cm_1_put_ack:
_I2Cm_1_put_ack:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >Port_1_DriveMode_0_SHADE
    M8C_SetBank1                                           ; Assert SCL low
    or    [Port_1_DriveMode_0_SHADE],I2Cm_1_SCL_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A
    M8C_SetBank0

    RAM_SETPAGE_CUR >I2Cm_1_bStatus    
                                                       ; Check if ack is to be transmitted
    tst   [I2Cm_1_bStatus],I2Cm_1_SEND_ACK

    RAM_SETPAGE_CUR >Port_1_DriveMode_0_SHADE
    M8C_SetBank1

    jz    noputack
                                                           ; Assert SDA low
    or    [Port_1_DriveMode_0_SHADE],I2Cm_1_SDA_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

    jmp   putack1
noputack:                                                  ; Release SDA high
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SDA_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

putack1:
    mov   A,I2Cm_1_delayqtr                                ; Delay 1/4 period
    call  I2Cm_1_delay
                                                           ; Release SCL high
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SCL_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

    M8C_SetBank0
clockstretch5:                                             ; Wait for SCL high in case slave
                                                           ; adds wait states.
    tst   reg[I2Cm_1_I2CPRTDR],I2Cm_1_SCL_pin
    jz    clockstretch5
                                                           ; delay for the high half of the clock.
    mov   A,I2Cm_1_delayhalf                               ; Delay 1/2 period
    call  I2Cm_1_delay

    M8C_SetBank1                                           ; Assert SCL low
    or    [Port_1_DriveMode_0_SHADE],I2Cm_1_SCL_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A
                                                           ; If there is another read pending
                                                           ; must release SDA for slave
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SDA_pin       ; Release SDA high
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A
    M8C_SetBank0

    RAM_SETPAGE_CUR >I2Cm_1_bStatus    
    mov   A, [I2Cm_1_bData]
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_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.
;          
;    Currently only the page pointer registers listed below are modified: 
;          CUR_PP
;
;  THEORY of OPERATION or PROCEDURE:
;     Send stop by releasing SDA high while SCL high.ASA21CR1
;
 I2Cm_1_SendStop:
_I2Cm_1_SendStop:
    RAM_PROLOGUE RAM_USE_CLASS_4
    RAM_SETPAGE_CUR >Port_1_DriveMode_0_SHADE
    M8C_SetBank1                                           ; Assert ACK and SDA low
    or    [Port_1_DriveMode_0_SHADE],I2Cm_1_SCL_pin|I2Cm_1_SDA_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

    mov   A,I2Cm_1_delay3qtr                               ; Delay 3/4 period
    call  I2Cm_1_delay
                                                           ; Release SCL high
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SCL_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

    M8C_SetBank0
clockstretch6:                                             ; Wait for SCL to go high in case slave
                                                           ; has added wait states.
    tst   reg[I2Cm_1_I2CPRTDR],I2Cm_1_SCL_pin
    jz    clockstretch6
    M8C_SetBank1

    mov   A,I2Cm_1_delay3qtr                               ; Delay 3/4 period
    call  I2Cm_1_delay

                                                           ; Release SDA high
    and   [Port_1_DriveMode_0_SHADE],~I2Cm_1_SDA_pin
    mov   A,[Port_1_DriveMode_0_SHADE]
    mov   reg[I2Cm_1_I2CPRTDM0],A

    mov   A,I2Cm_1_delayhalf                               ; Delay 1/2 period
    call  I2Cm_1_delay
    M8C_SetBank0
    
    RAM_EPILOGUE RAM_USE_CLASS_4
    ret
.ENDSECTION

.SECTION
;-----------------------------------------------------------------------------
;  FUNCTION NAME: I2Cm_1_delay
;
;  DESCRIPTION:
;    Create delays for I2Cm_1 routines.
;
;-----------------------------------------------------------------------------
;
;  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.
;          
I2Cm_1_delay:                                    ; 11 cycles for call. 32 total.
I2Cm_1delay1:                                    ; Delay 1/4 period at 100 kHz
     dec  A                                      ; 4 cycles
     jnz  I2Cm_1delay1                           ; 5 cycles for jump, 4 no jump.     
     ret                                         ; 8 cycles
  
.ENDSECTION



; End of File I2Cm_1.asm


