	.include "2313def.inc"

	.EQU	ADDR_WR=0xA0
	.EQU	ADDR_RD=0xA1
	.EQU	MkLan=1 	;SDA
;---------------- !Remark Unused sensor! ----------------------------
	.EQU	DS_Type=4 	;Termosensor DS18B20,DS1822
;	.EQU	DS_Type=7 	;Termosensor DS18S20,DS1820,DS1920,DS1620



	.DEF 	TIME_L	=R1	;(Global)
	.DEF 	TIME_H	=R2	;(Global)
	.DEF 	TMPR_L	=R3	;(Global)
	.DEF 	TMPR_H	=R4	;(Global)
	.DEF 	EETMP_L=R5	;(Global)
	.DEF 	EETMP_H=R6	;(Global)
	.DEF 	LNTMPR_L=R7	;(Global)
	.DEF 	LNTMPR_H=R8	;(Global)
	.DEF 	LineBisy=R9	;(Global)	Bisy I2C/MkLan Lines, Counter for MicroLan Conversion
	.DEF 	IND_CNT	=R10	;(Global)
	.DEF 	KeyIN	=R11	;(Global)
	.DEF	KeySold	=R12	;(Global)	KeyDTMP Summed KeyIN
	.DEF	KeyS	=R13	;(Global)	KeyS will be in R13
	.DEF 	KeyInOld=R14	;(Global)	KeyInOld will be in R14
	.DEF	ACK	=R15	;(Global)	Flag ACK "I2C device READY/CONTINUED TRANSFER"

	.DEF 	KeyD	=R20	;(Global)	KeyD will be in R20
	.DEF 	DL1	=R21	;(Global)	GP Timer 
	.DEF	RST25	=R22	;(Global)	Timer "Reset 25Sec"
	.DEF 	RING	=R23	;(Global)	Flag/Counter Cycling CLC/Tmpr
	.DEF	TmKEY	=R24	;(Global)	Time during KEY Pressed
	.DEF 	Points	=R25	;(Global)	Points in BIND0/BIND1


;======================== *** SRAM SEGMENT ***==============================

		.DSEG 	;SRAM memory segment

BIND0:		.byte	4		;Buffer IND N0
BIND1:		.byte	4		;Buffer IND N1
BIN:		.byte	2		;binary form location H/L bytes
DDEC:		.byte	5		;decimal form location MSB(0)-LSB(4)
PCFTM_L:	.byte	1		;BIN Time PCF (LOW)
PCFTM_H:	.byte	1		;BIN Time PCF (HIGH)
I2C_YES:	.byte	1		;Flag I2C_PRESENT
MkLan_YES:	.byte	1		;Flag MkLan_PRESENT
AUTORPT:	.byte	1		;Autorepeat constant (Nx0.02Sec)
TERMOCLC:	.byte	1		;Counter for MicroLan Conversion
TRMFLAG:	.byte	1		;Indication Flag For Termothreshold
ClcPoint:	.byte	1		;Points for CLC mode
;======================== *** CODE SEGMENT ***==============================

	.CSEG     	 		;begin of program memory
	.org 0

;-----------------SETUP INTERRUPTS HANDLERS---------------------------------

reset:	rjmp	start			; 00 Reset Handler
	reti				; 01 IRQ0 Handler
	reti				; 02 IRQ1 Handler
	reti				; 03 Timer1 Capture Handler
	reti				; 04 Timer1 Compare Handler
	reti				; 05 Timer1 Overflow Handler (Sound Alarm INT Programm)
	rjmp	TimeKey			; 06 Timer0 Overflow Handler (Main INT Programm)
	reti				; 07 UART RX Complete Handler
;	reti				; 08 UDR Empty Handler
;	reti				; 09 UART TX Complete Handler
;	reti				; 0A Analog Comparator Handler
	
;--------------------- Messages & Constants --------------------------------
IND_POS:	.db	0xF7, 0xFB,0xFD,0xFE
	; SYMBOLS      "0"  "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"  "A"  "b"  "C"  "d"  "E"  "F"
SSEG_SYM:	.db	0xDB,0x48,0xE3,0xEA,0x78,0xBA,0xBB,0xC8,0xFB,0xFA,0xF9,0x3B,0x93,0x6B,0xB3,0xB1
	; SYMBOLS      " "  " "  " "  " "  "1"  "8"  "2." "0"  "2"  " "  " "  " "  " " 
MSG_VER:	.db	0x00,0x00,0x00,0x00,0x48,0xFB,0xE7,0xDB,0xE3,0x00,0x00,0x00,0x00
CLC:		.db	0x93,0x13,0x93,0x00
PG:		.db	0xF1,0x9B
toC:		.db	0x00,0x33,0xF0,0x93
dconst:		.DW 	10000,1000,100,10,1
clcconst:	.DW 	1440,600,60,10,1
trmconst:	.DW 	25600,2560,256,26,3

;----------------------- BEGIN OF PROGRAMM ---------------------------------

;---------------------- *** SETUP PART *** ---------------------------------

start:	
	
	ldi	r16,0xdf		;stack init SP=0xdf
	out	spl,r16			;

	sbi	ACSR,ACD		;Analog comparator off

	ldi	r16,0xFF		;Set Ini Ports func (DIRECTION)
	out	ddrb,r16		;	DDRB

	ldi	r16,0x0F		;Set Ini Ports value (VALUE)
	out	portb,r16		;	PORTB

	ldi	r16,0x68		;Set Ini Ports func (DIRECTION)
	out	ddrd,r16		;	DDRD

	ldi	r16,0x14		;Set Ini Ports value (VALUE)
	out	portd,r16		;	PORTD

	ldi	r16,0x04
	out	TCCR0,r16		;T/C0 CK/256
	ldi	r16,0x02
	out	TIMSK,r16		;T/C0 Overflow INT enable

	ldi	r16,0x0E		;Watchdog timer enable (1Sec)
	out	WDTCR,r16		;

;--------------------- Registers clearing ----------------------------------
	clr	r31			;Load 0=>MSB (Z)
	ldi	r30,0x1D		;Load 29=>LSB (Z)
RgClr:	st	Z,R31			;0=>R(Z)
	dec	R30			;Counter=counter-1
	brne	RgClr			;Do until counter=0
;---------------------------------------------------------------------------
;------------------- Restore Mode PCF --------------------------------------
	rcall	RST_PCF			;Restore mode PCF & Global INT Enable
;---------------------------------------------------------------------------
	ser	RST25			;SET WDT Reset max
	;----- Conditional VERSION Message --------------
	ldi	r17,0x0F	;
	mov	LineBisy,r17	;Set LineBisy Enable
	ldi 	DL1,4 		;set time delay 
	rcall	delay		;Wait 
	tst	KeyS		;? key pressed ?
	breq	verend		;if NO then go over

	;--------- CLEAR EEPROM -------------------------	
	cli			;DISABLE Interrupts
	ldi	r17,0x7F	;SET max addr EEPROM
	out	EEDR,r31	;0=>EEPROM data
ver1:	sbic	EECR,EEWE	;
	rjmp	ver1		;Wait EEPROM Ready
	out	EEAR,r17	;Set EEPROM addr
	sbi	EECR,EEMWE	;Set MASTER Write Enable
	sbi	EECR,EEWE	;Set Write Enable
	dec	r17		;Dec Counter
	brge	ver1		;IF addr>=0 REPIT
	sei			;ENABLE Interrupts
	;------------------------------------------------

VER:	ldi	ZL,MSG_VER*2	;load MSG ADDR
	add	ZL,r16

	ldi	XL,BIND0	;load BIND0
	rcall	SSEG_BIND	;sent SYM*4=>BIND0
	rcall	SSEG_BIND	;sent SYM*4=>BIND1
	
	ldi 	DL1,25 		;inter symbol delay
	rcall	delay		;Wait 
	ser	RST25		;SET WDT Reset max
	inc	r16
	cpi	r16,10
	brne	ver
verend:
	;------------------------------------------------

;======================= MAIN ===================================



	;************** CLOCK **************

CLOCK:	;------------ INTRO ------------------
	ldi	ZL,CLC*2	;load MSG ADDR
	rcall	INTRO		;display INTRO 1Sec
 	;-------------------------------------

clock5:	clr	Points		;Clear Points(pos0...3)
	;---------------- SYNCHRONIZATION -----------------------
	rcall	SYNCHRO		;Synchronization with INTERRUPTS	
	;---------------------------------------------------------
	;------------ Read stored Programm PG 00 -----------------
	clr	r17			;Set 1/2 1-st EEAddr PGM00
	rcall	RD_EE0			;Read 2*Data EEPROM (NOT Corrected)
	;---------------------------------------------------------
	;---------- Test Programm Activity -----------------------
	sbrc	EETMP_H,3	;IF PROGRAMM NOT ACTIVE
	;---------- Set Programm IND Points ---------------------
	ori	Points,0x80		;Set flashing point in 3 position
	sts	ClcPoint,Points	;Store Points for CLC mode
	ori	Points,0x04		;set flashing point in BINDx+1 (2 position)
	;--------------------------------------------------------
	;----------- Check PCF available -----------------
	lds	ACK,I2C_YES	;GET flag I2C_PRESENT
	tst	ACK		;IF ACK=0 (NO PCF available)
	brne	clock0		;then go TIME section
	rjmp	TMPR		;then go TMPR section
	;-------------------------------------------------
clock0:	ldi	r16,8		;Set Autorepeat constant 0.16Sec (Nx0.02Sec)
	sts	AUTORPT,r16	;

	;------------ Wait Key Pressed ------------------
clock2:	clr	KeyD
clock1:	;------------ Set INDICATION Termocontrol ---------------
	rcall	TRMPNT		;Set termostat points
	;---------------------------------------------------------
	lds	TIME_L,PCFTM_L	;READ Time	
	lds	TIME_H,PCFTM_H	;READ Time	
	rcall	DISPTIME	;Display Time	
	ser	RST25		;SET WDT Reset max
	;--------------- Ring Control ---------------------
	ser	r16		;FFh=>temp
	cp	RING,r16	;?RING=FFh?
	brne	clock6		;
	rjmp	TMPR0		;IF YES then GO to TEMPERATURE
	;--------------------------------------------------
clock6:	tst	KeyD		;? KeyD=0 ?
	breq	clock1		; if Yes then repit clock
	;------------------------------------------------

	cpi	KeyD,0x04	;KeyD=K2 ("Set")
	breq	CLC04		;goto SUB ON/OFF Programm

	cpi	KeyD,0x84	;KeyD="Set"_long
	breq	CLC84		;goto SUB 

	cpi	KeyD,0x08	;KeyD="Mode"_long 
	brne	clock3		;
	rjmp	TMPR		;
clock3:
	cpi	KeyD,0x88	;KeyD="Mode"_long 
	brne	Clock2		;
	rjmp	PROGRAMM	;goto PROGRAMM section	
;=========================================================

;================= CLC Keys handlers =====================
CLC84:	rcall	SETTIME		;Set New Time	
	rcall	TIME_BDD	;Convert TIME_BIN=>TIME_BDD
	rcall	WR_TIME		;WRITE new time in PCF
	rjmp	Clock2	
	;--------------------------------------------------
CLC04:	;---------------- SYNCHRONIZATION -----------------------
	rcall	SYNCHRO		;Synchronization with INTERRUPTS	
	;---------------------------------------------------------
	;------------ Read stored Programm point 00 --------------
	clr	r17		;Set 1/2 1-st EEAddr PGM00
	rcall	RD_EE0		;Read 2*Data EEPROM (NOT Corrected)
	;---------------------------------------------------------
	ldi	r16,0x08	;Load Invert constant
	eor	EETMP_H,r16	;ON/OFF Programm activity Flag
	mov	TIME_L,EETMP_H	;Prepare Writing(Data)
	inc	r17		;Prepare Writing(Addr)
	rcall	WR_EE0		;Write NEW Data
	rjmp	clock5		;GO TO begin TIME block

;=========================================================

.include "CLC_SUBS.asm"

	;----------- * * * ------------------

	;========= Clock SUBROUTINES ============

	;-------------- WRITE TIME SET ------------------
WR_TIME:
	;---------- Test LINE READY ----------------------
WT1:	sbrc	LineBisy,7	;IF LineBisy>0   (Line not Ready?)
	rjmp	WT1		;Then WAIT
	;------------------------------------------------	
	cli			;Disable Interrupts
	rcall	sta		;Start transfer I2C

	ldi	r16,ADDR_WR	;
	rcall	I2COUT		;Sent Slave PCF WRITE ADDR 

	clr	r16		;
	rcall	I2COUT		;Sent Sub ADDR (STATUS REG.)

	ldi	r16,0x80	;"STOP COUNTER" command
	rcall	I2COUT		;Sent Command

	clr	r16		;0=>.01/.1Sec
	rcall	I2COUT		;Sent DATA

	clr	r16		;0=>1/10Sec
	rcall	I2COUT		;Sent DATA

	mov	r16,TIME_L	;Sent MINUTES
	rcall	I2COUT		;Sent Command

	mov	r16,TIME_H	;Sent HOURS
	rcall	I2COUT		;Sent Command

	rcall	sto		;Stop transfer I2C

	;-------------- START COUNTER -------------------
	;============= Restore Mode PCF =================
RST_PCF:
	rcall	sta		;Start transfer I2C

	ldi	r16,ADDR_WR	;
	rcall	I2COUT		;Sent Slave PCF WRITE ADDR 

	clr	r16		;
	rcall	I2COUT		;Sent Sub ADDR (STATUS REG.)
  
	clr	r16		;
	rcall	I2COUT		;Sent Reset Data

	rcall	sto		;Stop transfer I2C
	;-------------------------------------------------	
	sei			;Enable Interrupts
	RET
	;=================================================


;=========================================================





	;************** "PROGRAMM" SECTION **************

	.def	PGM_ADDR	=r17
PROGRAMM:
	clr	PGM_ADDR		;Set 0=>"PGM ADDR"
pgm0:	;============= INTRO:Show PGM ADDR ================================
	clr	KeyD		;
	clr	Points		;Clear Points
	;----------- Convert BIN=> DDEC --------------
	clr	r18			;0=>HIGH byte BIN,(PGM_ADDR=LOW byte BIN)
	ldi	ZL,low(dconst*2)	;set Z pointer to DECconst in FLASH
	rcall 	BDD	
	;-------------- Header to INDICATOR -------------
	ldi	ZL,PG*2			;load MSG ADDR
	ldi	XL,BIND0		;load BIND0
	rcall	SSEG_BIND		;sent SYMB*4=>BIND0
	rcall	SSEG_BIND		;sent SYMB*4=>BIND1
	;------------ Sent DDEC to 2,3 pos INDICATOR -------------
	ldi	XL,BIND0+2		;Set pos in BIND0
	lds	r16,ddec+3		;load msb bdd
	rcall	BDD_BIND		;Sent BDD (low nibble in R16) to BIND0+2/BIND1+2
	lds	r16,ddec+4		;load LSB bdd
	rcall	BDD_BIND		;Sent BDD (low nibble in R16) to BIND0+3/BIND1+3
	;------------------ Wait 0.7Sec --------------------------
	ldi 	DL1,35 		;set delay 0.7 Sec  
	rcall	delay		;Wait 
	;=========================================================
	;--------------- Read EEPROM ----------------------------
	rcall	RD_EE		;READ EEPROM (With decoding)
	;---------- Show Blanc positions (Show "----") -------
	ldi	r16,0x20	;"-" =>temp
	ldi	XL,BIND0	;load BIND0
pgm2:	st	X+,r16		;"-" =>BIND (X)
	cpi	XL,BIND0+8	;?X=BIND0+8?
	brne	pgm2		;IF NO then repit
	;--------- CONTROL "DATA IS ACTIVE" ------------------
	sbrs	EETMP_H,3	;IF DATA active
	rjmp	pgm3		;THEN Show "----"
	;---------------- Display Time --------------------------
	rcall	DISPTIME	;Display Time	
	;================ Wait KEY Pressed ========================
pgm3:	tst 	KeyD		;IF NO KEY pressed
	breq	pgm3		;then Wait
	;-----------------------------------------------------------
	cpi	KeyD,0x01	;KeyD=K0 "+"
	breq	PGM01		;goto SUB 
		;----------------------------------------
	cpi	KeyD,0x02	;KeyD=K1 "-"
	breq	PGM02		;goto SUB 
		;----------------------------------------
	cpi	KeyD,0x08	;KeyD=K3 "Mode"
	brne	pgm4		;
	rjmp	CLOCK		;goto CLOCK 
pgm4:		;----------------------------------------
	cpi	KeyD,0x84	;KeyD=K3_Long "Set"
	breq	PGSET		;goto PGM SET SECTION 
		;----------------------------------------
		;----------------------------------------
	cpi	KeyD,0x88	;KeyD=K3_Long "Mode"
	brne	pgmE		;
	rjmp	TMPR		;goto TEMPERATURE SECTION 
		;----------------------------------------
pgmE:	rjmp	pgm0  		;Termination

;===================== PROGRAMM KEY HANDLERS ===========================
PGM01:	cpi	PGM_ADDR,60		;IF PGM Addr>60
	breq	PGM01E			;THEN GO OVER
	inc 	PGM_ADDR		;next Pgm Addr
PGM01E:	rjmp	pgmE
	;----------------------------------------------------
PGM02:	tst	PGM_ADDR		;IF PGM Addr=0
	breq	PGM02E			;THEN GO OVER
	dec	PGM_ADDR		;next Pgm Addr
PGM02E:	rjmp	pgmE
	;----------------------------------------------------

;=========================================================

.include "PGM_SUBS.asm"







	;************** TEMPERATURE **************

TMPR:	;------------ INTRO ------------------
	ldi	ZL,toC*2	;load MSG ADDR
	rcall	INTRO		;display INTRO 1Sec
	;-------------------------------------
	;---------- Check MkLan available ----------------
	lds	r16,MkLan_YES	;GET flag MkLan_PRESENT
	tst	r16		;IF MkLan_PRESENT=0 (NO MkLan available)
	brne	TMPR0		;then go TMPR section
	rjmp	CLOCK		;then go TIME section
	;-------------------------------------------------

TMPR0:	lds	Points,ClcPoint	;Load CLC mode points
	;				andi	Points,0x88	;Clear Points(pos0...2)
	;-------------------------------------------------
	ldi	r16,2		;Set Autorepeat constant 0.04Sec (Nx0.02Sec)
	sts	AUTORPT,r16	;
	;-------------------------------------------------

TMPR1:	clr	KeyD			;
TMPR2:	rcall	TRMPNT			;Set termostat points
	mov	TMPR_L,LNTMPR_L	;READ Termo	
	mov	TMPR_H,LNTMPR_H	;READ Termo	
	rcall	TERMOIND		;Display Temperature
	ser	RST25			;SET WDT Reset max
	;--------------- Ring Control ---------------------
	ser	r16		;FFh=>temp
	cp	RING,r16	;?RING=FFh?
	brne	TMPR3		;IF YES then GO to TIME
	rjmp	clock5		;IF YES then GO to TIME
	;--------------------------------------------------
TMPR3:	tst 	KeyD			;IF NO KEY pressed
	breq	TMPR2			;then next Display Temperature
	;--------------------------------------------------
	cpi	KeyD,0x04	;KeyD=K0 or K1 ("+"or"-")
	brlo	TRMSET		;goto SUB SHOW Threshhold

	cpi	KeyD,0x04	;KeyD=K2 ("Set")
	breq	TRMSET0		;goto SUB ON/OFF Threshhold

	cpi	KeyD,0x84	;KeyD=K2_Long ("Set"_long)
	breq	TRMSET		;

	cpi	KeyD,0x08	;KeyD=K3 ("Mode")
	brne	TMPR4		;
	rjmp	CLOCK		;goto CLOCK section 
	;------------ RING MODE --------------------------
TMPR4:	cpi	KeyD,0x88	;KeyD=K3_long ("Mode"_long)
	brne	TMPR1		;
	tst	RING		;?RING=0?
	breq	TMPR5		;
	clr	RING		;
	rjmp	TMPR		;goto TMPR section 
TMPR5:	inc	RING		;
	rjmp	CLOCK		;goto CLOCK section 

;=========================================================
.include "TERMO_SB.asm"








;===================== SUBROUTINES ============================

;---------------- Set INDICATION Termocontrol ----------------
TRMPNT:	cli
	andi	Points,0xEE		;Clear 0 pos points
	lds	r17,TRMFLAG		;Read Indication Flag For Termo
	or	Points,r17		;Set 0 pos points
	sei
	RET
;-------------------------------------------------------------

;----------- Sent BDD=>BIND0/1 (BDD in R16,pos BIND0 in X) ---
WBDD_BIND:	swap	r16		;swap HI/LO nibbles
		rcall	BDD_BIND	;sent low nibble
		swap	r16		;swap HI/LO nibbles
		rcall	BDD_BIND	;sent high nibble
		ret
;----- Sent LOW nibble R16=>BIND0/1,pos BIND0 in X R16 not change, pos BIND=pos+1 -------
BDD_BIND:	push	r16		;copy data
		andi	r16,0x0F	;mask low nibble
		ldi	ZL,SSEG_SYM*2	;load First SSEG SYM
		add	ZL,r16
		lpm
		ST	X,r0		;set Data in BIND0
		subi	XL,-4		;change addr BIND
		ST	X,r0		;set Data in BIND1
		subi	XL,3		;X=X+1 (Next POS in BIND0)
		pop	r16		;restore data
		ret
;-------------------------------------------------------------------------------

;------------- Sent SSEG*4=>BIND0/1 (ADDR SSEG in Z) -----------
SSEG_BIND:	push	r17	;store used registers
		ldi	r17,4
ssb1:		lpm		;read SYM
		ST	X+,R0	;sent SYM=>BINDx
		inc	ZL	;next MSG ADDR
		dec	r17
		brne	ssb1
		subi	ZL,4	;RESTORE MSG ADDR
		pop	r17	;restore used registers
		ret
;---------------------------------------------------------------

;--------- BINARY to DECIMAL format converter ------------------
	;(input 2 byte BIN(L/H),5 byte output DDEC (MSB...LSB)) 

	.def	BINL	=r17
	.def	BINH	=r18
	.def	tDDEC	=r19
	.def	CONL	=r20
	.def	CONH	=r21

BDD:	cli			;disable interrupts
	push	r16		;store used registers
	push	r17		;store used registers
	push	r18		;store used registers
	push	r19		;store used registers
	push	r20		;store used registers
	push	r21		;store used registers
	push	XL		;store used registers

	ldi	XL,low(ddec)	;set X pointer to DDEC results
	ldi	r16,5		;5=>COUNTER 

bdd1:	ldi	r19,0xFF	;-1=>DDEC

	lpm			;read LOW_DDCONST
	mov	r20,r0
	inc	ZL		;Z=Z+1
	lpm			;read HIGH_DDCONST
	mov	r21,r0
	inc	ZL		;Z=Z+1
	
bdd2:	inc	r19		;DDEC=DDEC+1
	sub	r17,CONL	;BIN-CON
	sbc	r18,CONH
	brsh	bdd2		;ret if bin>=con
	
	add	r17,CONL	;BIN+CON
	adc	r18,CONH
	st	X+,r19		;store DDEC
	dec	r16		;counter=counter-1
	brne	bdd1		;if not END go next DDEC

	pop	XL		;restore used registers
	pop	r21		;restore used registers
	pop	r20		;restore used registers
	pop	r19		;restore used registers
	pop	r18		;restore used registers
	pop	r17		;restore used registers
	pop	r16		;restore used registers

	sei			;enable interrupts
	ret
;---------------------------------------------------------------

;------------- Display INTRO 1Sec (MSG ADDR in ZL) -----------
INTRO:	clr	Points		;Clear Points(pos0...3)
	ldi	XL,BIND0	;load BIND0
	rcall	SSEG_BIND	;sent SYM*4=>BIND0
	rcall	SSEG_BIND	;sent SYM*4=>BIND1
	ldi 	DL1,50 		;set delay 1 Sec  
	rcall	delay		;Wait 
	ret
;---------------------------------------------------------------

;------------- Time Delay(Delay=DL1*1/50Sec) -----------
DELAY:	tst	DL1
	brne	delay
	ret
;---------------------------------------------------------------
;========================= E N D ===============================

.include "I2C.asm"
.include "timekey.asm"
