;************************************************************************
	list p=16F877
	#include p16F877.inc


	__CONFIG _CP_OFF & _WDT_OFF & _HS_OSC & _LVP_OFF & _BODEN_OFF

	#define	scroll_dir	TRISA,4
	#define	scroll		PORTA,4		;Push-button RA4 on PCB
	#define	select_dir	TRISB,0		
	#define	select		PORTB,0		;Push-button RB0 on PCB

	EXTERN	LCDInit, temp_wr, d_write, i_write, LCDLine_1, LCDLine_2

variables	UDATA 0x30
ptr_pos		RES 1
ptr_count	RES 1
temp_1		RES 1
temp_2		RES 1
temp_3		RES 1
cmd_byte	RES 1
temperature	RES 1
LSD			RES 1
MsD			RES 1
MSD			RES 1

NumH		RES 1
NumL		RES 1
TenK		RES 1
Thou		RES 1
Hund		RES 1
Tens		RES 1
Ones		RES 1

STARTUP CODE
	NOP
	goto	start
	NOP
	NOP
	NOP
PROG1 	CODE

stan_t	CODE	0x100	;start standard table at ROM 0x100	
stan_table				;table for standard code
	addwf	PCL,f
	dt		"zZzZzZzZzZzZzZzZ"	;0
	dt		"  :-| SLEEP     "	;16
	dt		"  Temperature   "	;32
	dt		"   RA4 = Exit 	 "	;48
	dt		"RA4=Exit  RB0=Ok"	;64
	dt		"   Temperature  "  ;80
	dt		"   measurement  "	;96

start	
	call LCDInit

	banksel	T1CON		;Configure Timer1 for real time clock
	movlw	0x0F		;	start here for timer "warm-up"
	movwf	T1CON

	banksel	TXSTA		;initialize USART		
	movlw	B'10100100'	;Master mode, 8-bit, Async, High speed
	movwf	TXSTA
	movlw	.25			;9.6Kbaud @ 4MHz
	movwf	SPBRG
	banksel	RCSTA
	movlw	B'10010000'
	movwf	RCSTA
	
	banksel	TRISC		;configure CCP1 module for buzzer
	bcf		TRISC,2

	banksel	T2CON		;bank 0
	movlw	0x05		;postscale 1:1, prescaler 4, Timer2 ON
	movwf	T2CON
		
	bsf		TRISA,4		;make switch RA4 an Input
	bsf		TRISB,0		;make switch RB0 an Input

;**************** STANDARD CODE MENU SELECTION *******************
;Introduction
	banksel	ptr_pos
	movlw	.80			;send "Temperature" to LCD
	movwf	ptr_pos
	call	stan_char_1

	movlw	.96			;send "MEASUREMENT" to LCD
	movwf	ptr_pos
	call	stan_char_2
	call	delay_1s	;delay for display
	call	delay_1s	;delay for display

;----------------- TEMPERATURE MEASUREMENT ----------------------
menu_temp	
	banksel	ptr_pos		;send "Temperature" to LCD
	movlw	.32
	movwf	ptr_pos
	call	stan_char_1

	banksel	ptr_pos		;send "RA4=Exit  RB0=Now" to lCD
	movlw	.64
	movwf	ptr_pos
	call	stan_char_2
t_wait
	banksel	PORTA		;bank 0
	btfss	select		;temperature measurement ??
	goto	temp		;YES
	btfss	scroll		;NO, next mode ??
	goto	exit		;NO
	goto	menu_temp	;beginning of menu
exit	
	movlw	.16			;send "SLEEP" to LCD
	movwf	ptr_pos
	call	stan_char_1
	movlw	.0			;send "-" to LCD
	movwf	ptr_pos
	call	stan_char_2
	sleep

;************* STANDARD USER CODE **********************************

;--------------------- BUZZER --------------------------------------
buzzer
	
	banksel	CCP1CON			;turn buzzer on		
	movlw	0x0F
	movwf	CCP1CON	

	banksel TRISB
	bcf		TRISB,3
	bcf		TRISB,2
	bcf		TRISB,1

	banksel PORTB
	bsf		PORTB,1
	call	delay_100ms
	call	delay_100ms
	banksel PORTB
	bcf		PORTB,1

	banksel PORTB
	bsf		PORTB,2
	call	delay_100ms
	call	delay_100ms
	banksel PORTB
	bcf		PORTB,2

	banksel PORTB
	bsf		PORTB,3
	call	delay_100ms
	call	delay_100ms
	banksel PORTB
	bcf		PORTB,3


	banksel PORTB
	bcf		PORTB,3

	movlw	0
	movwf	CCP1CON			;turn buzzer off
	goto	metka

;---------------------- Temperature -------------------------------- 
temp
;	This code if for the TC74A5-5.0VAT temperature sensor
;		1st. Check if temperature is ready to be read in config reg.
;		2nd. If ready, retireve temperatute in hex.
;		     If not ready, check config register again.

	banksel	TRISC			;initialize MSSP module
	bsf		TRISC,3
	bsf		TRISC,4
	movlw	B'00101000'
	banksel	SSPCON
	movwf	SSPCON
	banksel	SSPSTAT
	bsf		SSPSTAT,SMP
	movlw	.5
	movwf	SSPADD

	banksel	PIR1
	bcf		PIR1,TMR1IF		
	clrf	TMR1H			;load regs for 2 sec overflow
	clrf	TMR1L
get_temp
	banksel	cmd_byte
	movlw	0x01			;config register command byte
	movwf	cmd_byte
temp_now
	banksel	SSPCON2			;write to TC74
	bsf		SSPCON2,SEN
	btfsc	SSPCON2,SEN
	goto	$-1	
	movlw	B'10011010'		;send TC74 ADDRESS (write)
	banksel	SSPBUF	
	movwf	SSPBUF
	call	ssprw
	banksel	SSPCON2
	btfsc	SSPCON2,ACKSTAT		;ack?
	goto	$-1

	banksel	cmd_byte
	movf	cmd_byte,w		;send COMMAND byte (config)
	banksel	SSPBUF
	movwf	SSPBUF
	call	ssprw
	banksel	SSPCON2
	btfsc	SSPCON2,ACKSTAT	;ack?
	goto	$-1

	bsf		SSPCON2,RSEN	;send repeated start
	btfsc	SSPCON2,RSEN
	goto	$-1
	movlw	B'10011011'		;send TC74 ADDRESS (read)
	banksel	SSPBUF
	movwf	SSPBUF
	call	ssprw			;module idle?
	banksel	SSPCON2
	btfsc	SSPCON2,ACKSTAT	;ack?
	goto	$-1

	bsf		SSPCON2,RCEN	;enable receive mode
	btfsc	SSPCON2,RCEN
	goto	$-1

	banksel	SSPBUF			;retrieve config reg or temp reg
	movf	SSPBUF,w
	
	banksel	SSPCON2			;send NOT-ACK
	bsf		SSPCON2,ACKDT
	bsf		SSPCON2,ACKEN
	btfsc	SSPCON2,ACKEN
	goto	$-1
			
	bsf		SSPCON2,PEN		;stop
	btfsc	SSPCON2,PEN
	goto	$-1
	
	banksel	cmd_byte		;config command OR temp command
	btfss	cmd_byte,0
	goto	convert_temp	;get temperature ready for display

	andlw	0x40		
	sublw	0x40
	btfss	STATUS,Z		;is temp ready ??
	goto	get_temp		;NO, try again
	movlw	0x00			;YES, send temp command
	banksel	cmd_byte		;send temp register command
	movwf	cmd_byte
	goto	temp_now

convert_temp
	movwf	temperature
	call	bin_bcd			;NO, get temp ready for LCD
	call	LCDLine_1
	
	movlw	A'T'			;send "Temp=" to LCD
	movwf	temp_wr	
	call	d_write
	movlw	A'e'
	movwf	temp_wr	
	call	d_write
	movlw	A'm'
	movwf	temp_wr	
	call	d_write
	movlw	A'p'
	movwf	temp_wr	
	call	d_write
	movlw	0x20			;space
	movwf	temp_wr	
	call	d_write
	movlw	A'='
	movwf	temp_wr	
	call	d_write

	movlw	0x20			;space
	movwf	temp_wr	
	call	d_write

	movf	MSD,w			;send high digit
	movwf	temp_wr
	call	d_write
	movf	MsD,w			;send middle digit
	movwf	temp_wr
	call	d_write
	movf	LSD,w			;send low digit
	movwf	temp_wr
	call	d_write
	movlw	A'C'			;send "C" for Celsius
	movwf	temp_wr	
	call	d_write

	movlw	0x20			;space
	movwf	temp_wr	
	call	d_write
	movlw	0x20			;space
	movwf	temp_wr	
	call	d_write
	movlw	0x20			;space
	movwf	temp_wr	
	call	d_write
	
	call	LCDLine_2		;send "RB0 = Exit" to LCD
	banksel	ptr_pos			
	movlw	.48
	movwf	ptr_pos
	call	stan_char_2
	
	call	delay_100ms
	btfss	scroll			;exit ?
	goto	exit		
	btfsc	PIR1, TMR1IF	;2 second overflow occur ??
	call	write_eeprom	;YES
	goto	get_temp		;NO, get temperature again

							

;************************** ROUTINES ******************************		
;----Standard code, Place characters on line-1--------------------------
stan_char_1
	call	LCDLine_1		;mvoe cursor to line 1 
	banksel	ptr_count
	movlw	.16				;1-full line of LCD
	movwf	ptr_count
stan_next_char_1
	movlw	HIGH stan_table
	movwf	PCLATH
	movf	ptr_pos,w		;character table location
	call	stan_table		;retrieve 1 character
	movwf	temp_wr			
	call	d_write			;send character to LCD

	banksel	ptr_pos			;get next character for LCD
	incf	ptr_pos,f
	decfsz	ptr_count,f		;move pointer to next char
	goto	stan_next_char_1

	banksel	TXREG			;move data into TXREG 
	movlw	"\n"			;next line
	movwf	TXREG
	banksel	TXSTA
	btfss	TXSTA,TRMT		;wait for data TX
	goto	$-1
	banksel	TXREG			;move data into TXREG 
	movlw	"\r"			;carriage return
	movwf	TXREG
	banksel	TXSTA
	btfss	TXSTA,TRMT		;wait for data TX
	goto	$-1	
	banksel	PORTA			;bank 0
	
	return

;----Standard code, Place characters on line-2--------------------------
stan_char_2	
	call	LCDLine_2		;move cursor to line 2 
	banksel	ptr_count
	movlw	.16				;1-full line of LCD
	movwf	ptr_count
stan_next_char_2
	movlw	HIGH stan_table
	movwf	PCLATH
	movf	ptr_pos,w		;character table location
	call	stan_table		;retrieve 1 character
	movwf	temp_wr			
	call	d_write			;send character to LCD

	banksel	ptr_pos			;get next character for lCD
	incf	ptr_pos,f
	decfsz	ptr_count,f		;move pointer to next char
	goto	stan_next_char_2

	banksel	TXREG			;move data into TXREG 
	movlw	"\n"			;next line
	movwf	TXREG
	banksel	TXSTA
	btfss	TXSTA,TRMT		;wait for data TX
	goto	$-1
	banksel	TXREG			;move data into TXREG 
	movlw	"\r"			;carriage return
	movwf	TXREG
	banksel	TXSTA
	btfss	TXSTA,TRMT		;wait for data TX
	goto	$-1
	banksel	PORTA			;bank 0	

	return
;----------------------------------------------------------------------
; Мерцание светодиодов, подключённых к порту В
;FLASH
;	banksel TRISB		;Настройка выводов на выдачу
;	bcf		TRISB,3
;	bcf		TRISB,2
;	bcf		TRISB,1
;	banksel PORTB
;	bsf		PORTB,1	;Включение  1-госветодиода
;	call	delay_100ms
;	call	delay_100ms
;	banksel PORTB
;	bcf		PORTB,1	;Выключеие 1-го светодиода
;	bsf		PORTB,2
;	call	delay_100ms
;	call	delay_100ms
;	banksel	PORTB
;	bcf		PORTB,2
;	bsf		PORTB,3
;	call	delay_100ms
;	call	delay_100ms
;	banksel PORTB
;	bcf		PORTB,3
	
; Сравнение текущей температуры с заданной - (170C)
;compare_temp
;	banksel	temperature
;	movf 	temperature,w		
;	sublw	B'00010001'		;17
;	btfss	STATUS,0
;	goto	FLASH
;	;call	LCD_Clear
;	call	delay_100ms
;	call	stan_table
;------------------ 100ms Delay --------------------------------
delay_100ms
	banksel	temp_1
	movlw	0xFF
	movwf	temp_1
	movlw	0x83
	movwf	temp_2

	decfsz	temp_1,f
	goto	$-1
	decfsz	temp_2,f
	goto	$-3
	return

;---------------- 1s Delay -----------------------------------
delay_1s
	banksel	temp_1
	movlw	0xFF
	movwf	temp_1
	movwf	temp_2
	movlw	0x05

	movwf	temp_3
	decfsz	temp_1,f
	goto	$-1
	decfsz	temp_2,f
	goto	$-3
	decfsz	temp_3,f
	goto	$-5
	return	

;---------------- Binary (8-bit) to BCD -----------------------
;		255 = highest possible result
bin_bcd
	banksel	MSD
	clrf	MSD
	clrf	MsD
	movwf	LSD		;move value to LSD
ghundreth	
	movlw	.100		;subtract 100 from LSD
	subwf	LSD,w
	btfss	STATUS,C	;is value greater then 100
	goto	gtenth		;NO goto tenths
	movwf	LSD		;YES, move subtraction result into LSD
	incf	MSD,f		;increment hundreths
	goto	ghundreth	
gtenth
	movlw	.10		;take care of tenths
	subwf	LSD,w
	btfss	STATUS,C
	goto	over		;finished conversion
	movwf	LSD
	incf	MsD,f		;increment tenths position
	goto	gtenth
over				;0 - 9, high nibble = 3 for LCD
	movf	MSD,w		;get BCD values ready for LCD display
	xorlw	0x30		;convert to LCD digit
	movwf	MSD
	movf	MsD,w
	xorlw	0x30		;convert to LCD digit
	movwf	MsD
	movf	LSD,w
	xorlw	0x30		;convert to LCD digit
	movwf	LSD
	retlw	0

;---------------- Binary (16-bit) to BCD -----------------------
;		xxx = highest possible result
bin16_bcd			; Takes number in NumH:NumL 
	               	; Returns decimal in TenK:Thou:Hund:Tens:Ones 
        swapf   NumH,w 
        andlw   0x0F             
        addlw   0xF0             
        movwf   Thou 
        addwf   Thou,f 
        addlw   0xE2 
        movwf   Hund 
        addlw   0x32 
        movwf   Ones 

        movf    NumH,w 
        andlw   0x0F 
        addwf   Hund,f 
        addwf   Hund,f 
        addwf   Ones,f 
        addlw   0xE9 
        movwf   Tens 
        addwf   Tens,f 
        addwf   Tens,f 

        swapf   NumL,w 
        andlw   0x0F 
        addwf   Tens,f 
        addwf   Ones,f 

        rlf     Tens,f 
        rlf     Ones,f 
        comf    Ones,f 
        rlf     Ones,f 

        movf    NumL,w 
        andlw   0x0F 
        addwf   Ones,f 
        rlf     Thou,f 

        movlw   0x07 
        movwf   TenK 

        movlw   0x0A                             ; Ten 
Lb1: 
        addwf   Ones,f 
        decf    Tens,f 
        btfss   3,0 
         goto   Lb1 
Lb2: 
        addwf   Tens,f 
        decf    Hund,f 
        btfss   3,0 
         goto   Lb2 
Lb3: 
        addwf   Hund,f 
        decf    Thou,f 
        btfss   3,0 
         goto   Lb3 
Lb4: 
        addwf   Thou,f 
        decf    TenK,f 
        btfss   3,0 
         goto   Lb4 

        retlw   0

;---------------------------- EEPROM WRITE -------------------------------
write_eeprom	
	banksel	SSPCON2			;write to EEPROM
	bsf	SSPCON2,SEN		;start bit
	btfsc	SSPCON2,SEN
	goto	$-1	
	movlw	B'10100000'		;send control byte (write)
	banksel	SSPBUF	
	movwf	SSPBUF
	call	ssprw
	banksel	SSPCON2
	btfsc	SSPCON2,ACKSTAT		;ack?
	goto	$-1

	movlw	0x00			;send slave address HIGH byte
	banksel	SSPBUF
	movwf	SSPBUF
	call	ssprw
	banksel	SSPCON2
	btfsc	SSPCON2,ACKSTAT		;ack?
	goto	$-1

	movlw	0x05			;send slave address LOW byte(0x0005)
	banksel	SSPBUF
	movwf	SSPBUF
	call	ssprw
	banksel	SSPCON2
	btfsc	SSPCON2,ACKSTAT		;ack?
	goto	$-1

	banksel	temperature
	movf	temperature,w		;send slave DATA = temperature

	sublw	B'00011001'		;25
	btfss	STATUS,0
	goto	buzzer
metka
	movwf	SSPBUF
	call	ssprw
	banksel	SSPCON2
	btfsc	SSPCON2,ACKSTAT		;ack?
	goto	$-1

	bsf	SSPCON2,PEN		;stop bit
	btfsc	SSPCON2,PEN
	goto	$-1
		
	banksel	TMR1L
	bcf	PIR1,TMR1IF		;clear TIMER1 overflow flag
	clrf	TMR1L			;clear registers for next overflow
	clrf	TMR1H

	return
;------------------------ IDLE MODULE -------------------------------------
ssprw					;check for idle SSP module 
	movlw	0x00
	banksel	SSPCON2
	andwf	SSPCON2,w
	sublw	0x00
	btfss	STATUS,Z
	goto	$-4

	btfsc	SSPSTAT,R_W
	goto	$-1
	return

;---------------------------------------------------------------------------
	end	
