Up one I2C assembly source. By Lee Davison. Up to top

I2C Assembly source.

This is the code that drives the I2C bus on the dart control board. The routine Getadrak is to allow access to the bus via the USR() function in EhBASIC.

An example of it's use can be found here.


* I2C bus scan assembly code.

* This code is fully relocatable so no ORG address is given

* Once the code is loaded into memory it needs the user vector to be set
* to the address of Getadrak. It is then called with USR(ad) where ad is
* the I2C bus device address to test. The value returned is 0 for no ack,
* -1 for ack.

URT_BASE	EQU	$80000		* UART base address

URT_IP		EQU	URT_BASE+$1B	* input port
URT_OPbs	EQU	URT_BASE+$1D	* output port set bit
URT_OPbc	EQU	URT_BASE+$1F	* output port clear bit

* these values correct for version 1.10 of EhBASIC68

LAB_EVBY	EQU	$2536		* evaluate byte parameter
LAB_24D5	EQU	$2760		* normalise FAC1
FAC1_m		EQU	$40594		* FAC1 mantissa
FAC1_e		EQU	$40598		* FAC1 exponent
FAC1_s		EQU	$40599		* FAC1 sign

* address device and get ack as true/false

Getadrak
	BSR.s	I2C_start	* generate I2C start
	JSR	LAB_EVBY	* get byte parameter
	BSR.s	I2C_wrby	* write I2C byte, returns /ack in d0
	MOVE.w	d0,FAC1_e	* possibly clear exponent & sign
	BEQ.s	LAB_noak	* branch if there was no ack

	MOVE.w	#$A080,FAC1_e	* set exponent & sign for -1
LAB_noak
	MOVE.l	d0,FAC1_m	* save mantissa
	BSR.s	I2C_stop	* generate I2C stop
	JMP	LAB_24D5	* normalise FAC1 & return

* generate I2C start

I2C_start
	BSR.s	I2C_dast	* set I2C data (UART op bit 7)
	BSR.s	delay_01	* count 1 delay
	BSR.s	I2C_ckst	* set I2C clock (UART op bit 6)
	BSR.s	delay_01	* count 1 delay
	BSR.s	I2C_dacl	* clear I2C data (UART op bit 7)
	BSR.s	delay_01	* count 1 delay
	BSR.s	I2C_ckcl	* clear I2C clock (UART op bit 6)
	BRA.s	delay_01	* count 1 delay

* generate I2C stop

I2C_stop
	BSR.s	I2C_dacl	* clear I2C data (UART op bit 7)
	BSR.s	delay_01	* count 1 delay
	BSR.s	I2C_ckst	* set I2C clock (UART op bit 6)
	BSR.s	delay_01	* count 1 delay
	BSR.s	I2C_dast	* set I2C data (UART op bit 7)

* count 1 delay (approx 106 cycles)

delay_01
	MOVE.l	d7,-(sp)	* save d7
	MOVE.l	(sp)+,d7	* restore d7
	MOVE.l	d7,-(sp)	* save d7
	MOVE.l	(sp)+,d7	* restore d7
	RTS

* set I2C clock bit (UART op bit 6)

I2C_ckst
	MOVE.b	#$40,URT_OPbs	* set I2C clock (UART op bit 6)
	RTS

* clear I2C data bit (UART op bit 7)

I2C_dacl
	MOVE.b	#$80,URT_OPbc	* clear I2C data (UART op bit 7)
	RTS

* set I2C data bit (UART op bit 7)

I2C_dast
	MOVE.b	#$80,URT_OPbs	* set I2C data (UART op bit 7)
	RTS

* clear I2C clock bit (UART op bit 6)

I2C_ckcl
	MOVE.b	#$40,URT_OPbc	* clear I2C clock (UART op bit 6)
	RTS

* wait for I2C clock bit to rise (UART ip bit 4)

I2C_wccl
	BTST	#4,URT_IP	* read UART input port
	BEQ.s	I2C_wccl	* loop if clock bit low

	BRA.s	delay_01	* now do delay

* write I2C byte, returns /ack in d0

I2C_wrby
	MOVE.l	d1,-(sp)	* save d1
	MOVEQ	#7,d1		* eight (0 - 7) bits to do
LAB_3172
	BTST	d1,d0		* test bit n of byte
	BEQ.s	LAB_317E	* branch if bit = 0

	BSR.s	I2C_dast	* set I2C data (UART op bit 7)
	BRA.s	LAB_3184	* skip clear

LAB_317E
	BSR.s	I2C_dacl	* clear I2C data (UART op bit 7)
LAB_3184
	BSR.s	delay_01	* count 1 delay
	BSR.s	I2C_ckst	* set I2C clock (UART op bit 6)
	BSR.s	I2C_wccl	* wait for I2C clock bit to rise
	BSR.s	I2C_ckcl	* clear I2C clock (UART op bit 6)
	BSR.s	delay_01	* count 1 delay
	DBF	d1,LAB_3172	* decrement bit count and loop until done

	BSR.s	I2C_dast	* set I2C data (UART op bit 7)
	BSR.s	delay_01	* count 1 delay
	BSR.s	I2C_ckst	* set I2C clock (UART op bit 6)
	BSR.s	I2C_wccl	* wait for I2C clock bit to rise
	MOVEQ	#0,d0		* clear sent byte
	BSR.s	I2C_rdbi	* read I2C data into d0 bit 0
	BSR.s	I2C_ckcl	* clear I2C clock (UART op bit 6)
	BSR.s	delay_01	* count 1 delay
	MOVE.l	(sp)+,d1	* restore d1
	BCHG	#0,d0		* test and change ack I2C bit
	RTS

* read I2C data into d0 bit 0

I2C_rdbi
	BTST	#5,URT_IP	* read UART input port
	BEQ.s	LAB_3136	* branch if data bit low

	ADDQ.b	#1,d0		* set bit 0 if I2C bit set
LAB_3136
	RTS

I2C Waveforms.

I2C start waveform
generated by I2C_start. I2C stop waveform
generated by I2C_stop.


Last page update: 4th May, 2004. e-mail me e-mail