;______________________________________________________________________________
;
; PROGRAM     : XTALL_Si570_Psdr.asm
;
; HARDWARE    : 12F683 @ 4 MHz
; ASSEMBLER   : MPASM v5.01  / case sensitive
;
; NEEDS       : P12F683.INC
;
; AUTHOR      : Cesco HB9TLK
;               Francis F6HSI
;             
;______________________________________________________________________________
;
;                                 DIRECTIVES
;______________________________________________________________________________

  list       p = 12F683, n = 0 , r = dec , x = OFF, st = ON

  include    P12F683.INC

  __config  _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTOSC

;______________________________________________________________________________
;
;                                 CONSTANTS
;______________________________________________________________________________


#define SCL 	GPIO,5 		; IIC Clock   (pin 2)
#define SDA 	GPIO,4 		; IIC Data    (pin 3)
#define SIN 	GPIO,3 		; RS232 Input (pin 4) 

#define SCL_H 	bsf SCL
#define SCL_L  	bcf SCL

#define Bank_0  bcf STATUS,RP0
#define Bank_1	bsf STATUS,RP0

#define SdaIn	bsf TRISIO,4
#define SdaOut	bcf TRISIO,4

;______________________________________________________________________________
;
;                                 Variables
;______________________________________________________________________________

Temp		equ 	0x21
BitCount	equ	0x22
rs232in		equ	0x23	;empfangenes byte

d1		equ	0x26
d2		equ	0x27
d3		equ	0x28
d4		equ	0x29
d5		equ	0x2a
d6		equ	0x2b

Buffer		equ 	0xa0	;This is in bank 1 

;______________________________________________________________________________
;
;                                 Program
;______________________________________________________________________________

  	ORG  	0
	clrf	STATUS

Init:
 	movlw	b'00000111'	;				  
	movwf	CMCON0		;digital I/O			  
	bsf	STATUS,RP0	;bank 1				  
	clrf	ANSEL		;digital I/O			  
	movlw	b'01100001'	;				  
	movwf	OSCCON		;4-mhz INTOSC system clock	  
	movlw	b'00001111'	;GP5 output, all others output	 
	movwf	TRISIO	
 	movlw 	B'00000000'
  	movwf	OPTION_REG
	bcf	STATUS,RP0	;bank 0	
  	movlw 	B'00110000'
  	movwf 	GPIO

tst:
  	call  	Freeze
  	call  	I2C_Start

  	movlw 	0xAA			; Send slave address + write bit
  	call  	I2C_Tx
  	movlw 	0x7			; Send register address
  	call  	I2C_Tx
  	movlw	0xE3 
	call  	I2C_Tx          	; -> reg 7
 	movlw	0xC2 
  	call  	I2C_Tx          	; -> reg 8
 	movlw	0xB6 
  	call  	I2C_Tx          	; -> reg 9
 	movlw	0xDA 
  	call  	I2C_Tx          	; -> reg 10
 	movlw	0x33 
  	call  	I2C_Tx          	; -> reg 11
 	movlw	0x24
  	call  	I2C_Tx          	; -> reg 12

  	call  	I2C_Stop
  	call  	Unfreeze
  	call  	Newf

Loop:

Serial:
	call	ser_RX			; Code von RS232 empfangen
	movlw	0x08	
	subwf	rs232in,0		; Compare to 0x08
	btfss	STATUS,Z
	goto	Serial			; No, was something else

	call	ser_RX			; get next, should be 0xaa
	movlw	0xaa	
	subwf	rs232in,0		; Compare to 0xaa
	btfss	STATUS,Z
	goto	Serial			; No, was something else

	call	ser_RX			; get next, should be 0x07
	movlw	0x07	
	subwf	rs232in,0		; Compare to 0x07
	btfss	STATUS,Z
	goto	Serial			; No, was something else

	call	ser_RX			; Code von RS232 empfangen
	movfw	rs232in			
	movwf	d1			; store it. 

	call	ser_RX			; Code von RS232 empfangen
	movfw	rs232in			
	movwf	d2			; store it. 

	call	ser_RX			; Code von RS232 empfangen
	movfw	rs232in			
	movwf	d3			; store it. 

	call	ser_RX			; Code von RS232 empfangen
	movfw	rs232in			
	movwf	d4			; store it. 

	call	ser_RX			; Code von RS232 empfangen
	movfw	rs232in			
	movwf	d5			; store it. 

	call	ser_RX			; Code von RS232 empfangen
	movfw	rs232in			
	movwf	d6			; store it. 

WriteSi570:				; Download values to the Si570
  	call  	Freeze
  	call  	I2C_Start

  	movlw 	0xAA			; Send slave address + write bit
  	call  	I2C_Tx
  	movlw 	0x7			; Send register address
  	call  	I2C_Tx
  	movfw	d1			; Send register values
	call  	I2C_Tx          	; -> reg 7
 	movfw	d2
  	call  	I2C_Tx          	; -> reg 8
 	movfw	d3
  	call  	I2C_Tx          	; -> reg 9
 	movfw	d4
  	call  	I2C_Tx          	; -> reg 10
 	movfw	d5
  	call  	I2C_Tx          	; -> reg 11
 	movfw	d6
  	call  	I2C_Tx          	; -> reg 12

  	call  	I2C_Stop
  	call  	Unfreeze
  	call  	Newf
	goto	Loop

;______________________________________________________________________________

I2C_Start:          			; Wenn SDA und SCL beide High, dann SDA auf Low ziehen
 	SCL_H
    	bcf   	SDA             	; Clear latch
	Bank_1				  
	SdaIn				; Set SDA as input
  	nop
  	nop
   	SdaOut		          	; Set SDA as output
  	Bank_0	
  	nop
  	SCL_L
  	RETURN

;------------------------------------------------------------------------------

I2C_Stop:           			; SCL ist Low und SDA ist Low
  	nop
  	nop
  	SCL_H
  	nop
	Bank_1			  
	SdaIn				; Set SDA as input
 	Bank_0				  
  	RETURN

;------------------------------------------------------------------------------

I2C_Tx:             			; Send a byte (in w) to the slave
 	Bank_1			  
	movwf	Buffer	  
	Bank_0				  
  	movlw 	8			; I2C_Bit_Count = 8
  	movwf 	BitCount
Tx_Repeat:
   	bcf   	SDA             	; Clear latch
	Bank_1			  
  	rlf   	Buffer,f
  	btfss 	STATUS,C
  	SdaOut          		; Set SDA as output
  	btfsc 	STATUS,C
 	SdaIn				; Set SDA as input
 	Bank_0				  
   	SCL_H				; SCL pulse
  	nop
  	nop
  	nop
  	SCL_L
  	decfsz 	BitCount,f
  	goto   	Tx_Repeat	 
  
  					; Get ACK from slave
	Bank_1			  
	SdaIn				; Set SDA as input
 	Bank_0				  
  	SCL_H
  	nop                   	
  	nop
  	nop
  	SCL_L
    	bcf   	SDA             	; Clear latch
	Bank_1				  
  	SdaOut		          	; Set SDA as output
  	Bank_0	
	return			  

;------------------------------------------------------------------------------

Newf:               		; Set the NewFreq bit (bit 6 of Register 135)

  	call 	I2C_Start
  	movlw 	0xAA		; Send slave address
  	call  	I2C_Tx
  	movlw 	135		; Send register address
  	call  	I2C_Tx
  	movlw 	b'01000000'	; Set bit 6
  	call  	I2C_Tx
  	call  	I2C_Stop
  	RETURN

;------------------------------------------------------------------------------

Freeze: 			; Freeze the DCO (bit 4 of Register 137)

  	call 	I2C_Start
  	movlw 	0xAA		; Send slave address 
  	call  	I2C_Tx  	
  	movlw 	137		; Send register address
  	call  	I2C_Tx 	
  	movlw 	b'00010000'	; Set bit 4
  	call  	I2C_Tx
  	call  	I2C_Stop
  	RETURN

;------------------------------------------------------------------------------


Unfreeze:           		; UnFreeze the DCO (bit 4 of Register 137)

  	call 	I2C_Start
  	movlw 	0xAA		; Send slave address
  	call  	I2C_Tx
  	movlw 	137		; Send register address
  	call  	I2C_Tx
  	movlw 	b'00000000'	; Clear bit 4
  	call  	I2C_Tx
  	call  	I2C_Stop
  	RETURN

;______________________________________________________________________________


ser_RX:				;empfangen eines Byte nach 'byte', 'rs232in' und w
	clrf	rs232in		;! Nullsetzen
	movlw	8
	movwf	BitCount	;  8 mal
startbit:	
	btfss	SIN		;  warten bis Startbit
	goto	startbit
	call	Pause		; Zeitverzögerung 1/2 Bit
	btfss	SIN	
	goto	ser_RX
RX_2:	call	Warte		; Zeitverzögerung 1 Bit
	btfsc	SIN		;
	bcf	STATUS, C	; high -> 0
	btfss	SIN	;
	bsf	STATUS, C	; low  -> 1
				;
	rrf	rs232in, f	;
	decfsz	BitCount, f	;
	goto	RX_2		; 8 mal
	
	call	Warte		; Zeitverzoegerung 1 bit
	btfsc	SIN		; Stop-Bit 
	goto	ser_RX		; wenn kein StopBit 

	RETURN

;______________________________________________________________________________

;ein bit zeitverzoegerung
; dieses timing muß genau stimmen (5%)
;
; empfang           4 MHz    10 MHz
; 2400 Bps =          69d    173d
; 4800 Bps =          34d     86d
; 9600 Bps =          16d     43d 

;9600 bps = 0.10416 ms
;6*16 = 96 - because there are 10 more cycles in the loop -> 86/6 = 14.5
;6*32 = 192 - because there are 10 more cycles in the loop -> 182/6 = 30.5

Warte:	
	movlw	D'31'		; 4800 Bps / 4 MHz empfangen
	movwf	Temp 
Warte1:				; 6 Zyklen-Schleife
	nop
	nop
	nop
	decfsz	Temp, 1	
	goto	Warte1
	RETURN

;______________________________________________________________________________

;1/2 bit zeitverzoegerung
;
;                4 MHz       10 MHz
; 2400 Bps =  416T =  63d    157d
; 4800 Bps =          31d     78d
; 9600 Bps =          15d     39d 

Pause:	
	movlw	D'31'		; 4800 Bps / 4 MHz
	movwf	Temp
Pause2:				; 3 Zyklen Schleife
	decfsz	Temp, f	
	goto	Pause2
	RETURN

;______________________________________________________________________________
  end


