		list	p=16f628A             ; 16F628A can be used
		#include <p16f628A.inc>       ; processor specific variable definitions

		__config 0x3D18
		
	cblock	0xA0
	
	tdd
	digitindex
	dpi
	BCD
	
	endc

#define	SDA	TRISB,5
#define	SCL	TRISB,4	

ORG 0x0000
	goto	Setup
;*********************Main*********************************	
Setup
	movlw   0x07             ; kikapcsoljuk a komparátort
    movwf   CMCON 
	bsf		STATUS,RP0
	clrf	TRISA			; PORTA I/O-k kimenetek
	movlw	b'00000111'		; PORTB <3:0> bemenet, a többi kimenet
	movwf	TRISB
	movlw	.2
	movwf	tdd
	bcf		STATUS,RP0
	clrf	PORTA
	clrf	PORTB

Init_TDA
	bsf		STATUS,RP0
	call	START
	call	OUT_BYTE
	movlw	0x00
	call	OUT_BYTE
	movlw	0x6F
	call	OUT_BYTE
	movlw	0x7F
	call	OUT_BYTE
	movlw	0x80
	call	OUT_BYTE
	movlw	0xA0
	call	OUT_BYTE
	movlw	0xC0
	call	OUT_BYTE
	movlw	0xE0
	call	OUT_BYTE
	movlw	0x40
	call	OUT_BYTE
	call	STOP
	goto	$

; Writes W to RTC, address is in digitindex
; digitindex incremented afther execution

I2CByteWrite
	movwf	tdd					; Save data to be written to RTC
	CALL 	START				; Generate Start, returns with 10100000 RTCADDR in W
	CALL 	OUT_BYTE			; Send slave address byte + nack
	CALL 	OUT_BYTE_ADDR		; Send word  address byte + nack
	MOVF 	tdd, W				; Get output data
	CALL 	OUT_BYTE			; Send data byte + nack
	goto	ToStop

; Generate stop condition on I2C bus
STOP:							; SDA 0 -> 1 while SCL == 1
								; SCL must be LOW afther (N)ACK's CLOCK_PULSE
	CALL	LOW_SDA				; SDA -> 0 - NACK has done it
	CALL	HIGH_SCL			; SCL -> 1 and make 5us stop setup time

; Make SDA high by making it input
HIGH_SDA:						; high impedance by making SDA an input
	BSF 	SDA					; make SDA pin an input
	GOTO 	DELAY_5US			; SDA -> 1 and make 5us bus free time

; Generate start / repeated start condition on I2C bus
START:							; SDA 1 -> 0 while SCL == 1, then SCL -> 0
	BSF 	STATUS, RP0			; Bank 1 - Access TRISA
	CALL 	HIGH_SDA			; SDA 0 -> 1 ; wait 5 us - For repeated start
	CALL 	HIGH_SCL			; SCL 0 -> 1 ; make 5 us Start setup time
	CALL 	LOW_SDA				; SDA 1 -> 0 ; make 5 us Start hold  time
	GOTO 	LOW_SCL				; SCL 1 -> 0 ; wait 5 us

; Shift out a byte to I2C bus, clock in (n)ack, get data from digitindex
OUT_BYTE_ADDR
	MOVF	digitindex,w		; output address to be read

; Shift out a byte to I2C bus, clock in (n)ack, data is in w
OUT_BYTE:						; send o_byte on I2C bus
	movwf	BCD					; Store data to send
	MOVLW 	.8
	MOVWF 	FSR					; Loop for 8 bits
OUT_BIT:
	BTFSC 	BCD,7				; if  one, send a  one
	CALL 	HIGH_SDA			; SDA at logic one
	BTFSS 	BCD,7				; if zero, send a zero
	CALL 	LOW_SDA				; SDA at logic zero
	CALL 	CLOCK_PULSE			; SCL -> 1 ; 5 us wait, SCL -> 0 ; 5 us wait
	RLF 	BCD,F				; left shift, move mext bit to bit7
	DECFSZ 	FSR,F				; decrement bit counter - Leaves with FSR = 0
	GOTO 	OUT_BIT

; Clock in/out (n)ack
NACK:							; bring SDA high and clock, SDA must be input
	CALL 	HIGH_SDA
	CALL	CLOCK_PULSE			; SCL -> 1 ; 5 us wait, SCL -> 0 ; 5 us wait

; Make SDA low by making it output
LOW_SDA:						; SDA -> 0 ; 5 us wait
	BCF 	SDA					; make SDA pin an output
	GOTO 	DELAY_5US

; Generate clock pulse 			; SCL -> 1 ; 5 us wait, SCL -> 0 ; 5 us wait
CLOCK_PULSE:					; SCL momentarily to logic one
	CALL 	HIGH_SCL			; SCL -> 1 ; 5 us wait

; Make SCL low by making it output
LOW_SCL:						; SCL -> 0 ; 5 us wait
	BCF 	SCL					; make SCL pin an output
	GOTO	DELAY_5US

; Make SCL high by making it input
HIGH_SCL:						; SCL -> 1 ; wait 5 us
	BSF 	SCL					; make SCL pin an input

; Delay 5uS @ 20MHz
DELAY_5US:						; provides nominal >5 us delay @20MHz
								; 1 instuction takes 200ns
	MOVLW	 .8					; 0.2 us
	MOVWF 	dpi					; 0.2 us
DELAY_1:						; Loop of 3 inst. time
	DECFSZ 	dpi, F				; 7*0.2+0.4 us
	GOTO 	DELAY_1				; 7*0.4 us
	RETLW	0x88	;RTC_ADDR			; Return address of RTC for OUT_BYTE 0.4 us
	
ToStop
	CALL 	STOP				; Generate stop condition
	incf	digitindex,f		; Increment word address
	movf	tdd,W				; Return data just read
	bcf		STATUS,RP0			; Back to Bank 0
	return


END

