Upload
others
View
12
Download
0
Embed Size (px)
Citation preview
Communication - Using PSoC Internal Resistors for I2C Communications
August 29, 2003 Document No. 001-35979 Rev. ** 1
AN2121Author: Jason A. Goldstein
Associated Project: No Associated Part Family: CY8C25xxx, CY8C26xxx
GET FREE SAMPLES HERE
Software Version: NAAssociated Application Notes: None
Application Note Abstract This Application Note describes how to use the internal pull-up resistors present on the PSoC® I/O pins when communicating as an I2C™ Bus Master.
Introduction All devices that drive an I2C bus must use an open collector. A high value is driven on the bus by resistors tied to VCC. For a lightly loaded bus, it is possible to use the pull-up resistors built into each PSoC I/O pin instead of external resistors. This Application Note describes how to modify the I2C Bus Master Software User Module supplied with PSoC Designer™ to provide a choice of using either internal or external resistors.
Pull-Up Resistors and I2C Figure 1 shows a block diagram of a typical I2C system.
The pull-up resistors (RP) are determined by the supply voltage, clock speed and bus capacitance. The minimum sink current for any device (master or slave) should be no
less than 3 mA at VOLmax = 0.4 V for the output stage. This limits the minimum pull-up resistor value for a 5V
system to about 1.5 kΩ. The maximum value for RP is dependent on the bus capacitance and clock speed. For a 5 V system with a bus capacitance of 150 pF, the pull-up resistors should be no larger than 6 kΩ.
Each I/O pin on the PSoC has the option of driving the signal with a strong low signal and a weak high signal. The weak high voltage signal is provided with a pull-up resistor of at least 4 kΩ and no more than 8 kΩ (see section 13.2 of the PSoC Device Family Data Sheet). For a 5 V system with 8 kΩ pull-up resistors, the total bus capacitance is limited to 100 pF when using the internal pull-up resistors.
To avoid destroying the output driver of any of the parts, never use both external and internal resistors – use one or the other. Also, one and only one PSoC should use the internal resistors when connecting multiple PSoC devices in a system.
For more information on “The I2C-Bus Specification,” see the Philips web site at:
http://www.semiconductors.philips.com/buses/i2c.
Driving the Bus The I2C Bus Master User Module provided with PSoC Designer operates by toggling the I/O pins in software. A logic zero is provided by driving a strong 0 (Data 0, Drive Mode 11), and a logic one is provided by changing the pin to be high impedance (Data 0, Drive Mode 10). Thus, only Drive Mode Bit 0 must be toggled to change states. However, a bank mode switch is required to change any of the drive mode bits. The bank must be switched back after the modification is made.
When using the internal pull-up resistors, a logic low is provided as before but a resistive high is provided (Data 1, Drive Mode 11) instead of high impedance. The bank switches are avoided because the Drive Mode bits remain unchanged resulting in a slight performance increase.
Modifying the Code All of the files for the I2C Bus Master User Module can be found in the following directory:
C:\Program Files\Cypress MicroSystems\PSoC Designer\Data\StdUM\I2Cm_SW
(If you did not install to the default directory, you can locate the files at …\PSoC Designer\Data\StdUM\I2Cm_SW.)
[+] Feedback [+] Feedback
0BAN2121
The first step in modifying the User Module is to add an entry into the properties list so that the user can choose internal or external resistors from within PSoC Designer. Do this by modifying the I2Cm_SW.xml file. Cypress warns against doing this and provides no support for those who do. As such, it is highly recommended that you backup the entire directory before proceeding.
Figure 1. Typical I2C System
The I2C Bus Master User Module already has three parameters; I2C_Port, SDA_Pin and SCL_Pin, that together define which pins are used for the data and clock signals. A fourth parameter called Pullup must be added as shown in Listing 1. PSoC Designer will replace the string `@Pullup` in the source code files with 0 for external and 1 for internal resistors. Figure 2 shows the resulting change in the Device Editor.
Figure 2. Resulting User Module Parameters
Simple modifications of the assembly language source file I2Cm_SW.asm (shown in Listing 2) using the IF-ELSE-ENDIF assembler directives are used to toggle the I/O pins as necessary.
To facilitate this process, some of the bank switches were re-arranged. When external resistors are chosen, this code behaves exactly the same as that originally provided by Cypress.
PSoC Designer should be restarted to pick up the changes, but otherwise the module works exactly as expected. Add the module in the Device Editor and build the project as usual.
Testing the Module This software has been tested using the PSoC as the I2C Bus Master and a Cypress Semiconductor CY22393 Triple PLL Clock Generator as the only slave. The output frequencies are easily changed by loading the proper registers inside the CY22393 from a lookup table stored in the PSoC Flash memory.
Summary For lightly loaded I2C busses, the internal pull-up resistors on the I/O pins of the PSoC can be used instead of external resistors. Modification of the I2C Bus Master User Module provided with the PSoC Designer software permits internal or external resistor usage to be easily chosen from within the Device Editor.
August 29, 2003 Document No. 001-35979 Rev. ** 2
[+] Feedback [+] Feedback
0BAN2121
Listing 1 <!--***********************************************************************-->
<!-- Filename: I2Cm_SW.XML -->
<!-- Rev A, 2002 Oct 20 -->
<!-- Description: Library routines to control the software I2C Master. -->
<!-- Copyright (c) Cypress MicroSystems 2001-2002. All rights reserved. -->
<!--***********************************************************************-->
<PSOC_DEVICE_DB>
<USER_MODULE_LIST>
<USER_MODULE NAME="I2Cm_SW" TYPE="PSOC_DIG_COMM" HTML="I2Cm_SW.HTM"
ICON="I2Cm_SW.ico" METAFILE="I2Cm_SW.emf"
API_PATH_TYPE="CUSTOM"
RAM="4" ROM="585" VERSION="Rev A, 2002 Oct 20">
<SHAPE SHAPE_TYPE="NONE"/>
<PARAMETER_LIST>
<PARAMETER NAME="I2C_Port" TYPE="PORT" SOURCE="None" VALUE_TYPE="ENUM" MASK="0x00" VALUE="None" ORDER="0">
<PARAMETER_VALUE_LIST>
<PARAMETER_VALUE NAME="None" ORDER="0" VALUE="0" />
</PARAMETER_VALUE_LIST>
<SHADOW_REG_LIST>
<SHADOW_REG NAME="DriveMode_0" />
<SHADOW_REG NAME="DriveMode_1" />
<SHADOW_REG NAME="Data" />
</SHADOW_REG_LIST>
</PARAMETER>
<PARAMETER NAME="SDA_Pin" TYPE="PIN" SOURCE="I2C_Port" VALUE_TYPE="ENUM" VALUE="None"
PIN_SELECT="StdCPU" PIN_DRIVE="High Z" ORDER="1">
<PARAMETER_VALUE_LIST>
<PARAMETER_VALUE NAME="None" ORDER="0" VALUE="0" />
</PARAMETER_VALUE_LIST>
</PARAMETER>
<PARAMETER NAME="SCL_Pin" TYPE="PIN" SOURCE="I2C_Port" VALUE_TYPE="ENUM" VALUE="None"
PIN_SELECT="StdCPU" PIN_DRIVE="High Z" ORDER="2">
<PARAMETER_VALUE_LIST>
<PARAMETER_VALUE NAME="None" ORDER="0" VALUE="0" />
</PARAMETER_VALUE_LIST>
</PARAMETER>
August 29, 2003 Document No. 001-35979 Rev. ** 3
[+] Feedback [+] Feedback
0BAN2121
<PARAMETER NAME="Pullup" TYPE="API" SOURCE="None" VALUE_TYPE="ENUM" VALUE="External" MASK="0x00" ORDER="3">
<PARAMETER_VALUE_LIST>
<PARAMETER_VALUE NAME="External" ORDER="0" VALUE="00" />
<PARAMETER_VALUE NAME="Internal" ORDER="1" VALUE="01" />
</PARAMETER_VALUE_LIST>
</PARAMETER>
</PARAMETER_LIST>
<API_REGISTER_ALIAS_LIST/>
</USER_MODULE>
</USER_MODULE_LIST>
</PSOC_DEVICE_DB>
August 29, 2003 Document No. 001-35979 Rev. ** 4
[+] Feedback [+] Feedback
0BAN2121
Listing 2 ;------------------------------------------------------------------------------
; FILENAME: `@INSTANCE_NAME`.asm
; VERSION: REV A, 2002 Oct 20
;------------------------------------------------------------------------------
; DESCRIPTION:
; I2C Master User Module API.
;
; The original I2C Master module drives strong 0 to indicate a logic low level
; and high-Z to indicate a logic high level. This assumes external pull-ups
; on the SCL and SDA pins. For lightly load I2C busses the internal pull-ups
; of the PSoC should be fine.
;
; This module has been modified to drive strong 0 to indicate a logic low level
; and resistive 1 (ie. pull-up) to indicate a logic high level. Care is taken
; to make sure the pull-up is active when receiving.
;
; The modifications are easily identified as being surrounded by an
; IF `@Pullup`-ELSE-ENDIF construct. The orginal code is the ELSE portion.
; Some of the bank switch statements have been moved to minimize the number of
; IF-ELSE-ENDIF constructs.
;
;------------------------------------------------------------------------------
; Copyright (c) Cypress MicroSystems 2000-2002. All Rights Reserved.
;------------------------------------------------------------------------------
;
;-----------------------------------------------
; include instance specific register definitions
;-----------------------------------------------
include "m8c.inc"
include "`@INSTANCE_NAME`.inc"
;-------------------------------------------------------------------
; Declare the functions global for both assembler and C compiler.
;
; Note that there are two names for each API. First name is
; assembler reference. Name with underscore is name refence for
; C compiler. Calling function in C source code does not require
; the underscore.
;-------------------------------------------------------------------
August 29, 2003 Document No. 001-35979 Rev. ** 5
[+] Feedback [+] Feedback
0BAN2121
export `@INSTANCE_NAME`_Start
export _`@INSTANCE_NAME`_Start
export `@INSTANCE_NAME`_Stop
export _`@INSTANCE_NAME`_Stop
export `@INSTANCE_NAME`_fSendRepeatStart
export _`@INSTANCE_NAME`_fSendRepeatStart
export `@INSTANCE_NAME`_fSendStart
export _`@INSTANCE_NAME`_fSendStart
export `@INSTANCE_NAME`_SendStop
export _`@INSTANCE_NAME`_SendStop
export `@INSTANCE_NAME`_fReadBytes
export _`@INSTANCE_NAME`_fReadBytes
export `@INSTANCE_NAME`_bWriteBytes
export _`@INSTANCE_NAME`_bWriteBytes
export `@INSTANCE_NAME`_bWriteCBytes
export _`@INSTANCE_NAME`_bWriteCBytes
export `@INSTANCE_NAME`_fWrite
export _`@INSTANCE_NAME`_fWrite
export `@INSTANCE_NAME`_bRead
export _`@INSTANCE_NAME`_bRead
;-------------------------------------------------------------------
; Declare the varables for both the assembler and C compiler.
;
;-------------------------------------------------------------------
export `@INSTANCE_NAME`_bStatus
export _`@INSTANCE_NAME`_bStatus
export `@INSTANCE_NAME`_bData
export _`@INSTANCE_NAME`_bData
export `@INSTANCE_NAME`_bAddr
export _`@INSTANCE_NAME`_bAddr
area bss(RAM)
_`@INSTANCE_NAME`_bStatus:
`@INSTANCE_NAME`_bStatus: `@CTAB40`blk 1 ; Status during transfers
_`@INSTANCE_NAME`_bData:
`@INSTANCE_NAME`_bData: `@CTAB40`blk 1 ; Data transfered
_`@INSTANCE_NAME`_bXferCnt:
August 29, 2003 Document No. 001-35979 Rev. ** 6
[+] Feedback [+] Feedback
0BAN2121
`@INSTANCE_NAME`_bXferCnt: `@CTAB50`; Reused variable for counting transfered
_`@INSTANCE_NAME`_bAddr: `@CTAB50`; Bytes
`@INSTANCE_NAME`_bAddr: `@CTAB40`blk 1 ; Slave Address
_`@INSTANCE_NAME`_bit_count:
`@INSTANCE_NAME`_bit_count: `@CTAB40`blk 1 ; Bit counter
area text(ROM,REL)
`@INSTANCE_NAME`_SLAVE_ACKed: `@CTAB40`equ 0x01 ; This bit set if Slave ACKed Master
`@INSTANCE_NAME`_SEND_ACK: `@CTAB40`equ 0x10 ; If this flag set, Master should send ACK
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_Start
;
; DESCRIPTION: Call this function once to initialize the `@INSTANCE_NAME` bus.
; Sets up pins for `@INSTANCE_NAME` bus
;
; ARGUMENTS: none
;
; RETURNS: none
; SIDE EFFECTS: Resets all pins on the I2C master port to the pulldown drive
; mode.
;
; THEORY of OPERATION:
; none.
;
;-----------------------------------------------------------------------------
`@INSTANCE_NAME`_Start:
_`@INSTANCE_NAME`_Start:
IF `@Pullup`
; set pins to drive resistive high
or [`@I2C_Port_DriveMode_1_SHADE`],`@INSTANCE_NAME`_SDA_pin|`@INSTANCE_NAME`_SCL_pin
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SDA_pin|`@INSTANCE_NAME`_SCL_pin
ELSE
; Set pins to drive mode high Z
or [`@I2C_Port_DriveMode_1_SHADE`],`@INSTANCE_NAME`_SDA_pin|`@INSTANCE_NAME`_SCL_pin
and [`@I2C_Port_DriveMode_0_SHADE`],~(`@INSTANCE_NAME`_SDA_pin|`@INSTANCE_NAME`_SCL_pin)
ENDIF
August 29, 2003 Document No. 001-35979 Rev. ** 7
[+] Feedback [+] Feedback
0BAN2121
M8C_SetBank1 ; Setup port for normal operation
mov A,[`@I2C_Port_DriveMode_1_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM1],A
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
M8C_SetBank0
IF `@Pullup`
; set both pins high to apply the pull-ups
; only the data port needs to be changed from strong zero to a resistive 1
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SDA_pin|`@INSTANCE_NAME`_SCL_pin
ELSE
; Set both pins, low so that only the port
; mode has to be changed from a 0 to a 1
and [`@I2C_Port_Data_SHADE`],~(`@INSTANCE_NAME`_SDA_pin|`@INSTANCE_NAME`_SCL_pin)
ENDIF
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ret
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_Stop
;
; DESCRIPTION: This function performs no operation and is used for future
; module compatibility.
;
; ARGUMENTS: none
;
; RETURNS: none
;
;-----------------------------------------------------------------------------
`@INSTANCE_NAME`_Stop:
_`@INSTANCE_NAME`_Stop:
ret
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_ReadBytes
;
August 29, 2003 Document No. 001-35979 Rev. ** 8
[+] Feedback [+] Feedback
0BAN2121
; DESCRIPTION: Read multiple data bytes from 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 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: `@INSTANCE_NAME`_bStatus - Cleared if a slave responds to a request. Set otherwise
;
; SIDE EFFECTS: none.
;
; THEORY of OPERATION:
;
;-----------------------------------------------------------------------------
RxArray: equ 0
RxByteCount: equ -2
RxMode: equ -3
`@INSTANCE_NAME`_fReadBytes:
_`@INSTANCE_NAME`_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 [`@INSTANCE_NAME`_bStatus],0x00 `@CTAB60`; Clear all flags
tst [x+RxMode],`@INSTANCE_NAME`_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
tst [`@INSTANCE_NAME`_bStatus],`@INSTANCE_NAME`_SLAVE_ACKed
jz End_RD_Loop
; Send ACK until last byte
August 29, 2003 Document No. 001-35979 Rev. ** 9
[+] Feedback [+] Feedback
0BAN2121
or [`@INSTANCE_NAME`_bStatus],`@INSTANCE_NAME`_SEND_ACK `@CTAB60`; 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 [`@INSTANCE_NAME`_bStatus],~`@INSTANCE_NAME`_SEND_ACK `@CTAB60`; If last Byte, don't ACK
I2C_READ:
call `@INSTANCE_NAME`_read `@CTAB60`; Read a byte
pop x ; Restore x
push x ; Store x
mov x,[x+RxArray] ; Get pointer to data and put it in X
mov a,[`@INSTANCE_NAME`_bData] `@CTAB60`; Save data in data array
mov [x+RxArray],a ; Put read data in array
pop x ; Restore the original pointer
inc [x+RxArray] ; 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],`@INSTANCE_NAME`_NoStop
jnz SkipRxStop
call `@INSTANCE_NAME`_SendStop
SkipRxStop:
mov a,`@INSTANCE_NAME`_XFER_ERROR `@CTAB60`; Clear return value until we test if slave ACKed
tst [`@INSTANCE_NAME`_bStatus],`@INSTANCE_NAME`_SLAVE_ACKed `@CTAB60`; Test to see if Slave ACKed
jz End_ReadBytes
mov a,`@INSTANCE_NAME`_XFER_COMPLETE `@CTAB60`; Return ACKed True
End_ReadBytes:
ret
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_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)
August 29, 2003 Document No. 001-35979 Rev. ** 10
[+] Feedback [+] Feedback
0BAN2121
; [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: `@INSTANCE_NAME`_bStatus - Cleared if a slave responds to a request. Set otherwise
; RETURNS: `@INSTANCE_NAME`_bStatus - Cleared if a slave responds to a request. Set otherwise
;
; SIDE EFFECTS: none.
;
; THEORY of OPERATION:
;
;-----------------------------------------------------------------------------
TxArray: equ 0
TxByteCount: equ -2
TxMode: equ -3
`@INSTANCE_NAME`_bWriteBytes:
_`@INSTANCE_NAME`_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 [`@INSTANCE_NAME`_bStatus],0x00 `@CTAB55`; Clear all flags
tst [x+TxMode],`@INSTANCE_NAME`_RepStart
jnz DoRestartTx
call I2C_DoStart ; Send a start and address.
jmp DoTxAck
DoRestartTx:
call I2C_DoRepeatStart ; Send a repeat start and address.
DoTxAck:
mov [`@INSTANCE_NAME`_bXferCnt],0x00 `@CTAB55`; Zero out byte count first
tst [`@INSTANCE_NAME`_bStatus],`@INSTANCE_NAME`_SLAVE_ACKed `@CTAB55`; Test to see if Slave ACKed
jz End_WR_Loop
WR_Loop: ; Loop through bytes
push x ; Save X for later
mov x,[x+TxArray] ; Get pointer to data and put it in X
mov a,[x] ; Get data pointer to by X
August 29, 2003 Document No. 001-35979 Rev. ** 11
[+] Feedback [+] Feedback
0BAN2121
mov [`@INSTANCE_NAME`_bData],a `@CTAB55`; Save data in temp location
call `@INSTANCE_NAME`_write `@CTAB55`; Write the data
pop x
tst [`@INSTANCE_NAME`_bStatus],`@INSTANCE_NAME`_SLAVE_ACKed
jz DoWBstop ; Stop transfer if NAKed
inc [`@INSTANCE_NAME`_bXferCnt] `@CTAB55`; Increment transfer byte count
inc [x+TxArray] ; Advance pointer
dec [x+TxByteCount] ; Decrement byte counter
jnz WR_Loop ; Not finished, do another byte.
End_WR_Loop: ; Endloop
tst [x+TxMode],`@INSTANCE_NAME`_NoStop
jnz SkipTxStop
DoWBstop:
call `@INSTANCE_NAME`_SendStop
SkipTxStop:
mov a,[`@INSTANCE_NAME`_bXferCnt] `@CTAB55`; Return bytes transfered
End_WriteBytes:
ret
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_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: `@INSTANCE_NAME`_bStatus - Cleared if a slave responds to a request. Set otherwise
; RETURNS: `@INSTANCE_NAME`_bStatus - Cleared if a slave responds to a request. Set otherwise
;
; SIDE EFFECTS: none.
August 29, 2003 Document No. 001-35979 Rev. ** 12
[+] Feedback [+] Feedback
0BAN2121
;
; THEORY of OPERATION:
;
;-----------------------------------------------------------------------------
TxCArrayLSB: equ 0
TxCArrayMSB: equ -1
TxCByteCount: equ -2
TxCMode: equ -3
`@INSTANCE_NAME`_bWriteCBytes:
_`@INSTANCE_NAME`_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 [`@INSTANCE_NAME`_bStatus],0x00 `@CTAB55`; Clear all flags
tst [x+TxMode],`@INSTANCE_NAME`_RepStart `@CTAB55`; 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
mov [`@INSTANCE_NAME`_bXferCnt],0x00 ; Zero out byte count first
tst [`@INSTANCE_NAME`_bStatus],`@INSTANCE_NAME`_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 [`@INSTANCE_NAME`_bData],a `@CTAB55`; Save data in temp location
call `@INSTANCE_NAME`_write `@CTAB55`; Write the data
pop x
tst [`@INSTANCE_NAME`_bStatus],`@INSTANCE_NAME`_SLAVE_ACKed
jz DoWCBstop ; Stop transfer if NAKed
inc [`@INSTANCE_NAME`_bXferCnt] `@CTAB55`; Increment transfer byte count
inc [x+TxCArrayLSB] ; Advance LSB of pointer
jnc DecBCnt
August 29, 2003 Document No. 001-35979 Rev. ** 13
[+] Feedback [+] Feedback
0BAN2121
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],`@INSTANCE_NAME`_NoStop
jnz SkipTxCStop
DoWCBstop:
call `@INSTANCE_NAME`_SendStop
SkipTxCStop:
mov a,[`@INSTANCE_NAME`_bXferCnt] `@CTAB55`; Return bytes transfered
End_WriteCBytes:
ret
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_fSendRepeatStart
;
; DESCRIPTION: Send repeated start condition and send slave address.
;
; ARGUMENTS: `@INSTANCE_NAME`_bAddr - Contains the slave address and transfer direction.
;
; RETURNS: `@INSTANCE_NAME`_bSTatus - Cleared if a slave responds to a request. Set otherwise
;
; SIDE EFFECTS: none.
;
; THEORY of OPERATION: prepare to send start by setting SCl and SDA high.
; must be followed directly by `@INSTANCE_NAME`_start.
;
;-----------------------------------------------------------------------------
`@INSTANCE_NAME`_fSendRepeatStart:
_`@INSTANCE_NAME`_fSendRepeatStart:
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:
August 29, 2003 Document No. 001-35979 Rev. ** 14
[+] Feedback [+] Feedback
0BAN2121
push a
IF `@Pullup`
and [`@I2C_Port_Data_SHADE`],~`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Assert SCL low
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SDA_pin `@CTAB60`; Release SDA high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
M8C_SetBank1
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Assert SCL low
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SDA_pin `@CTAB60`; Release SDA high
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
ENDIF
; Delay 3/4 period
mov A,`@INSTANCE_NAME`_delay3qtr
call `@INSTANCE_NAME`_delay
IF `@Pullup`
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Release SCL high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
; Release SCL high
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SCL_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
M8C_SetBank0
ENDIF
clockstretch1: ; Wait for SCL high in case of wait
; states adde by slave
tst reg[`@INSTANCE_NAME`_I2CPRTDR],`@INSTANCE_NAME`_SCL_pin
jz clockstretch1
mov A,`@INSTANCE_NAME`_delay3qtr `@CTAB60`; Delay 1/2 period
call `@INSTANCE_NAME`_delay
pop a
jmp I2C_DoStart ; Jump through to I2C_DoStart
August 29, 2003 Document No. 001-35979 Rev. ** 15
[+] Feedback [+] Feedback
0BAN2121
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_fSendStart
;
; DESCRIPTION: Generates start condition and sends slave address.
;
; ARGUMENTS: A => Contains the slave address.
;
; RETURNS: `@INSTANCE_NAME`_bStatus - Cleared if a slave responds to a request. Set otherwise
;
; SIDE EFFECTS: none.
;
; THEORY of OPERATION: Send start by setting SDA low while SCL is high. Set
; SCL low in preparation to send address. Must be followed
; by `@INSTANCE_NAME`_write.
;
;-----------------------------------------------------------------------------
`@INSTANCE_NAME`_fSendStart:
_`@INSTANCE_NAME`_fSendStart:
asl a ; Shift address to the left
dec x ; If zero, C flag will be set
jc I2C_DoStart ; Do a write if zero
or a,0x01 ; Set Read flag
I2C_DoStart:
push A ; Save the slave address
IF `@Pullup`
and [`@I2C_Port_Data_SHADE`],~`@INSTANCE_NAME`_SDA_pin `@CTAB60`; Assert SDA low
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
M8C_SetBank1
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SDA_pin `@CTAB65`; Assert SDA low
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
ENDIF
mov A,`@INSTANCE_NAME`_delayhalf `@CTAB65`; Delay 1/2 period
call `@INSTANCE_NAME`_delay
August 29, 2003 Document No. 001-35979 Rev. ** 16
[+] Feedback [+] Feedback
0BAN2121
pop A ; Restore slave address to A
mov [`@INSTANCE_NAME`_bData],A
IF `@Pullup`
and [`@I2C_Port_Data_SHADE`],~`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Assert SCL low
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SCL_pin `@CTAB65`; Set SCL low
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
ENDIF
mov A,`@INSTANCE_NAME`_delayqtr `@CTAB65`; Delay 1/4 period
call `@INSTANCE_NAME`_delay
jmp `@INSTANCE_NAME`_write `@CTAB65`; Write the byte.
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_fWrite
;
; DESCRIPTION: Writes a byte to the I2C master bus.
;
; ARGUMENTS: Reg A contains Data
;
; RETURNS: 1 If ACKed, else 0
;
; SIDE EFFECTS: none.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
; FUNCTION NAME: `@INSTANCE_NAME`_write
;
; DESCRIPTION: Writes a byte to the I2C master bus. Also used for sending the address.
;
; ARGUMENTS: Reg A contains slave address.
; `@INSTANCE_NAME`_bData - Contains data to be transmitted.
;
; RETURNS: `@INSTANCE_NAME`_bStatus - Cleared if a slave responds to a request. Set otherwise
;
; SIDE EFFECTS: none.
August 29, 2003 Document No. 001-35979 Rev. ** 17
[+] Feedback [+] Feedback
0BAN2121
;
; THEORY of OPERATION: Send data byte to slave. Must be followed by `@INSTANCE_NAME`_get_ack.
;
;-----------------------------------------------------------------------------
`@INSTANCE_NAME`_fWrite:
_`@INSTANCE_NAME`_fWrite:
mov [`@INSTANCE_NAME`_bData],A `@CTAB60`; Put data in bData
`@INSTANCE_NAME`_write:
_`@INSTANCE_NAME`_write:
mov [`@INSTANCE_NAME`_bit_count],8 `@CTAB60` ; Set up count to xmit 8 bits
writenextbit:
dec [`@INSTANCE_NAME`_bit_count]
IF `@Pullup`
and [`@I2C_Port_Data_SHADE`],~`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Assert SCL low
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
M8C_SetBank1
; Assert SCL low
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SCL_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
ENDIF
rlc [`@INSTANCE_NAME`_bData]
jc write_bit ; Assert SDA low for data 0
IF `@Pullup`
and [`@I2C_Port_Data_SHADE`],~`@INSTANCE_NAME`_SDA_pin `@CTAB60`; Assert SDA low
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SDA_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
ENDIF
jmp writestartclock
August 29, 2003 Document No. 001-35979 Rev. ** 18
[+] Feedback [+] Feedback
0BAN2121
write_bit: ; Release SDA high for data 1
IF `@Pullup`
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SDA_pin `@CTAB60`; Release SDA high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SDA_pin `
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
ENDIF
writestartclock:
mov A,`@INSTANCE_NAME`_delayhalf `@CTAB60`; Delay 1/2 period
call `@INSTANCE_NAME`_delay
IF `@Pullup`
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Release SCL high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
; Release SCL High
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SCL_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
M8C_SetBank0
ENDIF
clockstretch2: ; Wait for SCL high in case of wait states
; are added by slave.
tst reg[`@INSTANCE_NAME`_I2CPRTDR],`@INSTANCE_NAME`_SCL_pin
jz clockstretch2
IF `@Pullup`
ELSE
M8C_SetBank1
ENDIF
; Delay for 1/2 period
mov A,`@INSTANCE_NAME`_delayhalf
call `@INSTANCE_NAME`_delay
cmp [`@INSTANCE_NAME`_bit_count],0
August 29, 2003 Document No. 001-35979 Rev. ** 19
[+] Feedback [+] Feedback
0BAN2121
jnz writenextbit
; jmp `@INSTANCE_NAME`_get_ack `@CTAB60`; This jump is not required since it falls
; through to `@INSTANCE_NAME`_get_ack
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_get_ack
;
; DESCRIPTION: Get slave acknowledge response. Used only by `@INSTANCE_NAME`_write.
;
; ARGUMENTS: `@INSTANCE_NAME`_bData - Contains data to be transmitted.
;
; RETURNS: Sets flag in `@INSTANCE_NAME`_bStatus if ACKed by Slave.
;
; SIDE EFFECTS: none.
;
; THEORY of OPERATION: Do the ack clock and check for Slave ACK
;
;-----------------------------------------------------------------------------
`@INSTANCE_NAME`_get_ack:
_`@INSTANCE_NAME`_get_ack:
IF `@Pullup`
and [`@I2C_Port_Data_SHADE`],~`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Assert SCL low
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
; Release SDA high so slave may ACK
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SDA_pin `@CTAB60`; Release SDA high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
; Assert SCL low
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SCL_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
; Release SDA high so slave may ACK
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SDA_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
ENDIF
August 29, 2003 Document No. 001-35979 Rev. ** 20
[+] Feedback [+] Feedback
0BAN2121
; Delay 3/4 period
mov A,`@INSTANCE_NAME`_delay3qtr
call `@INSTANCE_NAME`_delay
IF `@Pullup`
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Release SCL high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
; Release SCL high
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SCL_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
M8C_SetBank0
ENDIF
clockstretch3: ; Wait for SCL to go high in case wait states
; are added my slave.
tst reg[`@INSTANCE_NAME`_I2CPRTDR],`@INSTANCE_NAME`_SCL_pin
jz clockstretch3
; Clear ACK bit
and [`@INSTANCE_NAME`_bStatus],~`@INSTANCE_NAME`_SLAVE_ACKed
tst reg[`@INSTANCE_NAME`_I2CPRTDR],`@INSTANCE_NAME`_SDA_pin
jnz getack2 ; If ACKed, set flag
or [`@INSTANCE_NAME`_bStatus],`@INSTANCE_NAME`_SLAVE_ACKed
getack2:
mov A,`@INSTANCE_NAME`_delayhalf `@CTAB60`; Delay 1/2 period
call `@INSTANCE_NAME`_delay
mov A,[`@INSTANCE_NAME`_bStatus] `@CTAB60`; Get result and put it in A
and A,`@INSTANCE_NAME`_SLAVE_ACKed `@CTAB60`; Mask off just the ACK flag.
ret
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_read
;
; DESCRIPTION: Reads 1 data byte from the I2C master bus.
;
August 29, 2003 Document No. 001-35979 Rev. ** 21
[+] Feedback [+] Feedback
0BAN2121
; ARGUMENTS: Reg A Contains the Slave Address.
; `@INSTANCE_NAME`_bStatus - Set for no ack to be followed by stop.
; Clear for ack to indicate more data to follow.
;
; RETURNS: `@INSTANCE_NAME`_bData - Contains received data.
;
; SIDE EFFECTS: none.
;
; THEORY of OPERATION: Must be followed by `@INSTANCE_NAME`_put_ack.
;
;-----------------------------------------------------------------------------
`@INSTANCE_NAME`_bRead:
_`@INSTANCE_NAME`_bRead:
mov [`@INSTANCE_NAME`_bStatus],0x00 `@CTAB60`; Clear ACK flag
and A,0xFF ; Is Ack flag set"
jz `@INSTANCE_NAME`_read `@CTAB60`; Don't ACK
or [`@INSTANCE_NAME`_bStatus],`@INSTANCE_NAME`_SEND_ACK `@CTAB60`; Set ACK flag
`@INSTANCE_NAME`_read:
_`@INSTANCE_NAME`_read:
mov [`@INSTANCE_NAME`_bit_count],8 `@CTAB60`; Count and prepare bits to read
readnextbit:
dec [`@INSTANCE_NAME`_bit_count]
rlc [`@INSTANCE_NAME`_bData]
IF `@Pullup`
and [`@I2C_Port_Data_SHADE`],~`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Assert SCL low
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
M8C_SetBank1 ; Asser SCL low
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SCL_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
ENDIF
; Delay 1/2 period
mov A,`@INSTANCE_NAME`_delayhalf
call `@INSTANCE_NAME`_delay
IF `@Pullup`
August 29, 2003 Document No. 001-35979 Rev. ** 22
[+] Feedback [+] Feedback
0BAN2121
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Release SCL high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
; Release SCL high
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SCL_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
M8C_SetBank0
ENDIF
clockstretch4: ; Wait for SCL to go high in case slave
; addes wait states.
tst reg[`@INSTANCE_NAME`_I2CPRTDR],`@INSTANCE_NAME`_SCL_pin
jz clockstretch4
; Delay 1/4 period
mov A,`@INSTANCE_NAME`_delayqtr
call `@INSTANCE_NAME`_delay
and [`@INSTANCE_NAME`_bData],~01h `@CTAB60`; Record bit received
tst reg[`@INSTANCE_NAME`_I2CPRTDR],`@INSTANCE_NAME`_SDA_pin
jz readnobit
or [`@INSTANCE_NAME`_bData],01h
readnobit:
cmp [`@INSTANCE_NAME`_bit_count],0
jnz readnextbit ; Check for byte complete
; jmp `@INSTANCE_NAME`_put_ack `@CTAB60`; This jump is not required since it falls
; through to `@INSTANCE_NAME`_put_ack.
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_put_ack
;
; DESCRIPTION: Send acknowledge to slave. Used only by `@INSTANCE_NAME`_read
;
; ARGUMENTS: `@INSTANCE_NAME`_bStatus - Set for no ack to be followed by stop. Clear for ack
; to indicate more data to follow.
August 29, 2003 Document No. 001-35979 Rev. ** 23
[+] Feedback [+] Feedback
0BAN2121
;
; RETURNS: `@INSTANCE_NAME`_bData - Contains received data.
;
; SIDE EFFECTS: none.
;
; THEORY of OPERATION: Send ack if more data will follow.
;
;-----------------------------------------------------------------------------
`@INSTANCE_NAME`_put_ack:
_`@INSTANCE_NAME`_put_ack:
IF `@Pullup`
and [`@I2C_Port_Data_SHADE`],~`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Assert SCL low
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
M8C_SetBank1 ; Assert SCL low
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SCL_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
ENDIF
; Check if ack is to be transmitted
tst [`@INSTANCE_NAME`_bStatus],`@INSTANCE_NAME`_SEND_ACK
jz noputack
; Assert SDA low
IF `@Pullup`
and [`@I2C_Port_Data_SHADE`],~`@INSTANCE_NAME`_SDA_pin `@CTAB60`; Assert SDA low
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SDA_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
ENDIF
jmp putack1
noputack: ; Release SDA high
IF `@Pullup`
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SDA_pin `@CTAB60`; Release SDA high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
August 29, 2003 Document No. 001-35979 Rev. ** 24
[+] Feedback [+] Feedback
0BAN2121
ELSE
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SDA_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
ENDIF
putack1:
mov A,`@INSTANCE_NAME`_delayqtr `@CTAB60`; Delay 1/4 period
call `@INSTANCE_NAME`_delay
IF `@Pullup`
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Release SCL high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
; Release SCL high
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SCL_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
M8C_SetBank0
ENDIF
clockstretch5: ; Wait for SCL high in case slave
; adds wait states.
tst reg[`@INSTANCE_NAME`_I2CPRTDR],`@INSTANCE_NAME`_SCL_pin
jz clockstretch5
; delay for the high half of the clock.
mov A,`@INSTANCE_NAME`_delayhalf `@CTAB60`; Delay 1/2 period
call `@INSTANCE_NAME`_delay
IF `@Pullup`
and [`@I2C_Port_Data_SHADE`],~`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Assert SCL low
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
; If there is another read pending
; must release SDA for slave
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SDA_pin `@CTAB60`; Release SDA high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
August 29, 2003 Document No. 001-35979 Rev. ** 25
[+] Feedback [+] Feedback
0BAN2121
ELSE
M8C_SetBank1 ; Assert SCL low
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SCL_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
; If there is another read pending
; must release SDA for slave
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SDA_pin `@CTAB60`; Release SDA high
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
M8C_SetBank0
ENDIF
mov A, [`@INSTANCE_NAME`_bData]
ret
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_SendStop
;
; DESCRIPTION: Assert stop condition.
;
; ARGUMENTS: none
;
; RETURNS: none
;
; SIDE EFFECTS: none.
;
; THEORY of OPERATION: Send stop by releasing SDA high while SCL high.ASA21CR1
;
;-----------------------------------------------------------------------------
`@INSTANCE_NAME`_SendStop:
_`@INSTANCE_NAME`_SendStop:
IF `@Pullup`
and [`@I2C_Port_Data_SHADE`],~(`@INSTANCE_NAME`_SDA_pin|`@INSTANCE_NAME`_SCL_pin)
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
M8C_SetBank1 ; Assert ACK and SDA low
or [`@I2C_Port_DriveMode_0_SHADE`],`@INSTANCE_NAME`_SCL_pin|`@INSTANCE_NAME`_SDA_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
August 29, 2003 Document No. 001-35979 Rev. ** 26
[+] Feedback [+] Feedback
0BAN2121
ENDIF
mov A,`@INSTANCE_NAME`_delay3qtr `@CTAB60`; Delay 3/4 period
call `@INSTANCE_NAME`_delay
IF `@Pullup`
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SCL_pin `@CTAB60`; Release SCL high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
; Release SCL high
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SCL_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
M8C_SetBank0
ENDIF
clockstretch6: ; Wait for SCL to go high in case slave
; has added wait states.
tst reg[`@INSTANCE_NAME`_I2CPRTDR],`@INSTANCE_NAME`_SCL_pin
jz clockstretch6
mov A,`@INSTANCE_NAME`_delay3qtr `@CTAB60`; Delay 3/4 period
call `@INSTANCE_NAME`_delay
IF `@Pullup`
or [`@I2C_Port_Data_SHADE`],`@INSTANCE_NAME`_SDA_pin `@CTAB60`; Release SDA high
mov A,[`@I2C_Port_Data_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDR],A
ELSE
M8C_SetBank1
; Release SDA high
and [`@I2C_Port_DriveMode_0_SHADE`],~`@INSTANCE_NAME`_SDA_pin
mov A,[`@I2C_Port_DriveMode_0_SHADE`]
mov reg[`@INSTANCE_NAME`_I2CPRTDM0],A
M8C_SetBank0
ENDIF
mov A,`@INSTANCE_NAME`_delayhalf `@CTAB60`; Delay 1/2 period
August 29, 2003 Document No. 001-35979 Rev. ** 27
[+] Feedback [+] Feedback
0BAN2121
call `@INSTANCE_NAME`_delay
ret
;-----------------------------------------------------------------------------
; FUNCTION NAME: `@INSTANCE_NAME`_delay
;
; DESCRIPTION: create delays for `@INSTANCE_NAME` routines.
;
; ARGUMENTS: none
;
; RETURNS: none
;
; SIDE EFFECTS: none.
;
; THEORY of OPERATION: none.
;
;-----------------------------------------------------------------------------
`@INSTANCE_NAME`_delay: `@CTAB50`; 11 cycles for call. 32 total.
`@INSTANCE_NAME`delay1: `@CTAB50`; Delay 1/4 period at 100 kHz
dec A ; 4 cycles
jnz `@INSTANCE_NAME`delay1 `@CTAB50`; 5 cycles for jump, 4 no jump.
ret ; 8 cycles
;end of file
August 29, 2003 Document No. 001-35979 Rev. ** 28
[+] Feedback [+] Feedback
0BAN2121
August 29, 2003 Document No. 001-35979 Rev. ** 29
About the Author Name: Jason A. Goldstein
Title: Proprietor Background: Jason has a B.S. in Physics from Carnegie
Mellon University and an M.S. in Electrical Engineering from Northeastern University. He is the founder of Agitation Engines, a company based in Brookline Massachusetts. Agitation Engines provides critical thinking, design services and intellectual property at all stages of product development.
Contact: [email protected] www.agitationengines.com Agitation Engines 76 Parkman St. #1 Brookline, MA 02446 USA 617.278.9914
In March of 2007, Cypress recataloged all of its Application Notes using a new documentation number and revision code. This new documentation number and revision code (001-xxxxx, beginning with rev. **), located in the footer of the document, will be used in all subsequent revisions.
PSoC is a registered trademark of Cypress Semiconductor Corp. "Programmable System-on-Chip," PSoC Designer, and PSoC Express are trademarks of Cypress Semiconductor Corp. All other trademarks or registered trademarks referenced herein are the property of their respective owners.
Purchase of I2C components from Cypress or one of its sublicensed Associated Companies conveys a license under the Philips I2C Patent Rights to use these components in an I2C system, provided that the system conforms to the I2C Standard Specification as defined by Philips.
Cypress Semiconductor 198 Champion Court
San Jose, CA 95134-1709 Phone: 408-943-2600
Fax: 408-943-4730 http://www.cypress.com/
© Cypress Semiconductor Corporation, 2003-2007. The information contained herein is subject to change without notice. Cypress Semiconductor Corporation assumes no responsibility for the use of any circuitry other than circuitry embodied in a Cypress product. Nor does it convey or imply any license under patent or other rights. Cypress products are not warranted nor intended to be used for medical, life support, life saving, critical control or safety applications, unless pursuant to an express written agreement with Cypress. Furthermore, Cypress does not authorize its products for use as critical components in life-support systems where a malfunction or failure may reasonably be expected to result in significant injury to the user. The inclusion of Cypress products in life-support systems application implies that the manufacturer assumes all risk of such use and in doing so indemnifies Cypress against all charges.
This Source Code (software and/or firmware) is owned by Cypress Semiconductor Corporation (Cypress) and is protected by and subject to worldwide patent protection (United States and foreign), United States copyright laws and international treaty provisions. Cypress hereby grants to licensee a personal, non-exclusive, non-transferable license to copy, use, modify, create derivative works of, and compile the Cypress Source Code and derivative works for the sole purpose of creating custom software and or firmware in support of licensee product to be used only in conjunction with a Cypress integrated circuit as specified in the applicable agreement. Any reproduction, modification, translation, compilation, or representation of this Source Code except as specified above is prohibited without the express written permission of Cypress.
Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress reserves the right to make changes without further notice to the materials described herein. Cypress does not assume any liability arising out of the application or use of any product or circuit described herein. Cypress does not authorize its products for use as critical components in life-support systems where a malfunction or failure may reasonably be expected to result in significant injury to the user. The inclusion of Cypress’ product in a life-support systems application implies that the manufacturer assumes all risk of such use and in doing so indemnifies Cypress against all charges.
Use may be limited by and subject to the applicable Cypress software license agreement.
[+] Feedback [+] Feedback