;****************************************************************
;*--------------------------------------------------------------*
;*			Temperatuur lezing			*
;*--------------------------------------------------------------*
;****************************************************************
	LIST   P=PIC16F877A
	#INCLUDE P16F877A.INC

	__CONFIG        _CP_OFF & _DEBUG_OFF & _LVP_OFF & _PWRTE_ON & _WDT_OFF & _BODEN_OFF & _XT_OSC

;----------------------------------------------------------------
;Definieren van de registers en geheugenplaatsen
;----------------------------------------------------------------


KnoppenTemp	EQU	PORTA	;Knoppen voor temperatuurregeling

LCDControl	EQU	PORTB   ;Poort voor stuurFlag_Signbitalen LCD (= outputs)
ResSel		EQU	H'0004'	;Register Select Signal= pin4 LCD ;(0 = characters als kommando's aan LCD gegeven )					
ReadWrite	EQU	H'0003'	;Read Write Signal LCD = pin5 LCD (0 = schrijven)
Enable		EQU	H'0002' ;Enable signal LCD = pin6 LCD (initiatie communicatie tss LCD en PIC)

Sensor		EQU	PORTC	;
LCDData		EQU	PORTD	;Poort voor het doorsturen van characters (= outputs)

TC_SCK		EQU	H'0006'	;1=binnenhalen van bits, 0=niet
TC_CS		EQU	H'0000'	;aan/uit Maak dit controleerbaar. Moet dit wel, aangezien we toch op de klok zijn aangesloten van de PIC
				;Of toch niet, Kijk speciale functie van PORTC na en stel PORTC ook nog in om Serial Data te kunnen ontvangen
TC_SI		EQU	H'0004'	;data (temperatuur)
	


Temp_Lo		EQU	H'30'	;Denk eraan => elke geheugenplaats is = 1 byte, dus 8 bits (temp verdeelt over 2 bits)
Temp_Hi		EQU	H'31'

Counter		EQU	H'32'	; teller voor het aantal ingelezen bits van de temperatuur
Sign		EQU	H'33'
Flag_Signbit	EQU	H'0000'


TIMER1          EQU     H'20'
TIMER2          EQU     H'21'

TIMER3          EQU     H'34'   	
TIMER4          EQU     H'35'  

Tmax		EQU	H'36'	;Temperatuursinterval
Tmin		EQU	H'37'  


;++++++++++++++++++++++++++Begin+++++++++++++++++++++++++++++++++

		ORG	0
		call	RESET
		call	InitDisplay

		goto	main

		
;---------------------------------------------------------------
;Welke poort is input, welke is output
;---------------------------------------------------------------

RESET		
	bsf	STATUS,RP0	; reg. Bank 1
		
	;PORTA
	bcf	ADCON1,3	;Alles van PORTA digitaal zijn
	bsf	ADCON1,2
	bsf	ADCON1,1
	bsf	ADCON1,0
	movlw	B'001111'
	movwf	TRISA		; PortA = input (de niet gebruikte pinnen als output gedefinieerd)
		
	;PORTB
	movlw	B'11000011'	; in-/uitgang definities
	movwf	TRISB		 
	
	;PORTC
	movlw	B'00010000'	; in-/uitgang definities
	movwf	TRISC		; 
		
	;PORTD
	movlw	B'00000000'
	movwf	TRISD		; PortD = output


	bcf	STATUS,RP0	; reg. Bank 0

	;Alles op 0 zeten
	;PORTA
	movlw	B'000000'
	movwf	PORTA		; RA ports clear (=initiatie, uitgangen op 0 zetten) !!!!!!!!!!!!!!!!!!!!!!

	;PORTB
	movlw	B'00000000'
	movwf	PORTB		; RB ports clear (=initiatie, uitgangen op 0 zetten) !!!!!!!!!!!!!!!!!!!!!!

	;PORTC
	movlw	B'00000000'
	movwf	PORTC		; RC ports clear (=initiatie, uitgangen op 0 zetten) !!!!!!!!!!!!!!!!!!!!!!

	;PORTD
	movlw	B'00000000'
	movwf	PORTD		; RD ports clear (=initiatie, uitgangen op 0 zetten) !!!!!!!!!!!!!!!!!!!!!!

	;call	InitDisplay
	bsf	Sensor,TC_CS	;chip afzetten

	return

;----------------------------------------------------------------
;Delay
;----------------------------------------------------------------

Delay5		CLRWDT
		MOVLW   D'255'          
                MOVWF   TIMER1          
                
Delay6		MOVLW	D'255'
		MOVWF	TIMER2
		DECFSZ  TIMER2,F        
                GOTO    $-1             
                
		DECFSZ	TIMER1,F
		GOTO	Delay4	
		RETLW   0


Delay7		CLRWDT
		MOVLW   D'150'          
                MOVWF   TIMER3          
                
Delay8		MOVLW	D'150'
		MOVWF	TIMER4
		DECFSZ  TIMER4,F        
                GOTO    $-1             
                
		DECFSZ	TIMER3,F
		GOTO	Delay6	
		RETLW   0

;---------------------------------------------------------------
;Procedure die een bepaald character naar de diplay stuurt
;---------------------------------------------------------------




SendData					;Dit is een zeer algemene procedur om data te versturen, zowel voor LCDControl als LCDData
		movwf	LCDData			;De juiste waarde van LCDControl,ResSel hangt dus af van wat je wilt doen, verander deze waarde dus enkel in de hulpprocedures e niet in SendData
		bcf	LCDControl,Enable
		bsf	LCDControl,Enable	;E = 1, we kunnen schrijven naar de display (als R/W = 0, dit betekent schrijven en niet lezen)
		

		MOVLW   D'255'          ;*
                MOVWF   TIMER1          ;*
                ;
DELAY2		MOVLW	D'2'			; x msec
		MOVWF	TIMER2
		DECFSZ  TIMER2,F        ;*
                GOTO    $-1             ;*
                
		DECFSZ	TIMER1,F
		GOTO	DELAY2	
		RETLW   0


;--------------------------------------------------------------------------
;Procedure om alle characters naar de LCD te sturen (1 procedure per char)
;--------------------------------------------------------------------------

Send_A		movlw	A'A'	
		goto	SendData 
Send_B		movlw	A'B'	
		goto	SendData 
Send_C		movlw	A'C'	
		goto	SendData 
Send_D		movlw	A'D'	
		goto	SendData 
Send_E		movlw	A'E'	
		goto	SendData 
Send_F		movlw	A'F'	
		goto	SendData 
Send_G		movlw	A'G'	
		goto	SendData 
Send_H		movlw	A'H'	
		goto	SendData 
Send_I		movlw	A'I'	
		goto	SendData 
Send_J		movlw	A'J'	
		goto	SendData 
Send_K		movlw	A'K'	
		goto	SendData 
Send_L		movlw	A'L'	
		goto	SendData 
Send_M		movlw	A'M'	
		goto	SendData 
Send_N		movlw	A'N'	
		goto	SendData 
Send_O		movlw	A'O'	
		goto	SendData 
Send_P		movlw	A'P'	
		goto	SendData 
Send_Q		movlw	A'Q'	
		goto	SendData 
Send_R		movlw	A'R'	
		goto	SendData 
Send_S		movlw	A'S'	
		goto	SendData 
Send_T		movlw	A'T'	
		goto	SendData 
Send_U		movlw	A'U'	
		goto	SendData 
Send_V		movlw	A'V'	
		goto	SendData 
Send_W		movlw	A'W'	
		goto	SendData 
Send_X		movlw	A'X'	
		goto	SendData 
Send_Y		movlw	A'Y'	
		goto	SendData 
Send_Z		movlw	A'Z'	
		goto	SendData 
Send_a		movlw	A'a'	
		goto	SendData 
Send_b		movlw	A'b'	
		goto	SendData 
Send_c		movlw	A'c'	
		goto	SendData 
Send_d		movlw	A'd'	
		goto	SendData 
Send_e		movlw	A'e'	
		goto	SendData 
Send_f		movlw	A'f'	
		goto	SendData 
Send_g		movlw	A'g'	
		goto	SendData 
Send_h		movlw	A'h'	
		goto	SendData 
Send_i		movlw	A'i'	
		goto	SendData 
Send_j		movlw	A'j'	
		goto	SendData 
Send_k		movlw	A'k'	
		goto	SendData 
Send_l		movlw	A'l'	
		goto	SendData 
Send_m		movlw	A'm'	
		goto	SendData 
Send_n		movlw	A'n'	
		goto	SendData 
Send_o		movlw	A'o'	
		goto	SendData 
Send_p		movlw	A'p'	
		goto	SendData 
Send_q		movlw	A'q'	
		goto	SendData 
Send_r		movlw	A'r'	
		goto	SendData 
Send_s		movlw	A's'	
		goto	SendData 
Send_t		movlw	A't'	
		goto	SendData 
Send_u		movlw	A'u'	
		goto	SendData 
Send_v		movlw	A'v'	
		goto	SendData 
Send_w		movlw	A'w'	
		goto	SendData 
Send_x		movlw	A'x'	
		goto	SendData 
Send_y		movlw	A'y'	
		goto	SendData 
Send_z		movlw	A'z'	
		goto	SendData 
Send_0		movlw	A'0'	
		goto	SendData 
Send_1		movlw	A'1'	
		goto	SendData 
Send_2		movlw	A'2'	
		goto	SendData 
Send_3		movlw	A'3'	
		goto	SendData 
Send_4		movlw	A'4'	
		goto	SendData 
Send_5		movlw	A'5'	
		goto	SendData 
Send_6		movlw	A'6'	
		goto	SendData 
Send_7		movlw	A'7'	
		goto	SendData 
Send_8		movlw	A'8'	
		goto	SendData 
Send_9		movlw	A'9'	
		goto	SendData
Send_Space	movlw	A' '	
		goto	SendData 
Send_Question	movlw	A'?'	
		goto	SendData 
Send_Point	movlw	A'.'	
		goto	SendData 
Send_ArrowUp	movlw	B'00000010'		
		goto	SendData 
Send_ArrowDown	movlw	B'00000001'	
		goto	SendData 
Send_ArrowKies	movlw	B'00000000'	
		goto	SendData 
Send_ArrowRight	movlw	B'01111110'		
		goto	SendData 
Send_ArrowLeft	movlw	B'01111111'	
		goto	SendData 
Send_Dubbel	movlw	A':'	
		goto	SendData 
Send_Minus	movlw	A'-'	
		goto	SendData 
Send_Plus	movlw	A'+'	
		goto	SendData 
Send_Exclamation movlw	A'!'	
		goto	SendData
Send_Degrees	movlw	B'11011111'
		goto	SendData
Send_En		movlw	A'&'
		goto	SendData
Send_Equal	movlw	A'='
		goto	SendData

Send_GoHome
		bcf	LCDControl,ResSel
		movlw	B'00000010'	; Go to Home
		call	SendData 
		bsf	LCDControl,ResSel
		return

Send_ClearScreen
		bcf	LCDControl,ResSel	;RS = 0, byte aan PORTD zijn nu commando's
		movlw	B'00000001'		; Clear Display
		call	SendData 
		movlw	B'00000010'		; Go to Home
		call	SendData 
		bsf	LCDControl,ResSel
		return

Send_NextLine
		bcf	LCDControl,ResSel
		movlw	B'11000000'
		call	SendData
		bsf	LCDControl,ResSel
		return

Delay3		CLRWDT
		MOVLW   D'100'          
                MOVWF   TIMER1          
                
Delay4		MOVLW	D'100'
		MOVWF	TIMER2
		DECFSZ  TIMER2,F        
                GOTO    $-1             
                
		DECFSZ	TIMER1,F
		GOTO	Delay4	
		RETLW   0


;---------------------------------------------------------------
;Initialisatie van de display
;---------------------------------------------------------------

InitDisplay
		call	Delay3

		bcf	LCDControl,ReadWrite	;schrijven naar de display
		bcf	LCDControl,ResSel	;RS = 0, we sturen dus commando's naar de display
		call	Delay3

		movlw	B'00110000'
		call	SendData		
		call	Delay3

		movlw	B'00110000'
		call	SendData		
		call	Delay3

		movlw	B'00110000'
		call	SendData		
		call	Delay3

		movlw	B'00111000'		;Function set
		call	SendData		;2 maal een 8bit line, volgens de datasheet
		call	Delay3

		movlw	B'00001110'		;Display on/off Control
		call	SendData
		call	Delay3	
	
		movlw	B'00000110'		;Entry Mode Set
		call	SendData
		bsf	LCDControl,ResSel	;RS = 1, we sturen dus terug characters naar de display	
		call	Delay3	

		return

;****************************************************************
;		Lezen van de temperatuur			
;****************************************************************

;---------------------------------------------------------------
;Loop waarin de temp bit per bit wordt gelezen
;---------------------------------------------------------------

TempRead

	movlw	D'16'
	movwf	Counter

	bcf	Sensor,TC_SCK	;Klok op nul zetten. Er wordt geen data ontvangen van de sensor
	bcf	Sensor,TC_CS	;Sensor opzetten

	call	Delay5
	call	Delay7
	return

TempLoop			;Er wordt in deze loop geen data ontvangen van de sensor 

	bsf	Sensor,TC_SCK	;Zet de klok naar de sensor toe op 1. Er wordt een nieuwe databit gelezen
				;Blijkbaar beslis je zelf wanneer de input TC_SI verandert

	btfsc	Sensor,TC_SI	;Als TC_SI = 1
	bsf	STATUS,C	;wordt de Carry = 1
	btfss	Sensor,TC_SI	;Als TC_SI = 0
	bcf	STATUS,C	;wordt de Carry = 0
				;TC_SI is initieel = MSB, om dan bij elke doorgang van de loop te veranderen in de waarde rechts van de vorige

	call	Delay5
	bcf	Sensor,TC_SCK	;De klok SCK is nu = 0 en wordt dus geen data meer gelezen

	rlf	Temp_Lo		;De data wordt bit per bit in het register in gelezen met een rotate left through Carry = zie code hierboven
	rlf	Temp_Hi		;De rotate left hier gebruikt de waarde die C heeft verkregen door de vorige rlf
				;Zo schrijven we dus bit per bit het 16 bit getal in 2 registers

	decfsz	Counter,F	;Counter - 1, als deze uitkomst = 0 

	goto 	TempLoop	;niet meer opnieuw TempLoop uitvoeren

	call	Delay5
	bsf	Sensor,TC_CS	;uitschakelen van sensor

	call	Delay5
	return


;****************************************************************
;		Temperatuursregeling - Start			
;****************************************************************

;----------------------------------------------------------------
;Initialisatie van de Tmax en Tmin
;----------------------------------------------------------------

Init_AllTemps
	movlw	B'00111100'	;Dit is de gereduceerde vorm van 15�C
	movwf	Tmin

	movlw	B'01100100'	;Dit is de gereduceerde vorm van 25�C
	movwf	Tmax

	movlw	B'01101100'	;Temp_Lo een waarde geven enkel om dit stuk code te testen
	movwf	Temp_Lo
	return

;----------------------------------------------------------------
;Regeling
;----------------------------------------------------------------

ControleMax

	movf	Tmax,w		;Tmax inschrijven in w
	subwf	Temp_Lo,0	;verschil (Temp_Lo - Tmax) maken en in w opslaan
	btfss   STATUS,C	;de PIC gebruikt de 2's complement methode om verschillen te berekenen.
				;verschil > 0 => carry = 1
				;verschil < 0 => carry = 0
	goto	ControleMin
	goto	Send_Cooling

ControleMin

	movf	Tmin,w		;Tmin inschrijven in w
	subwf	Temp_Lo,0	;verschil (Temp_Lo - Tmin) maken en in w opslaan
	btfsc   STATUS,C	;de pic gebruikt de 2's complement methode om verschillen te berekenen.
				;verschil > 0 => carry = 1
				;verschil < 0 => carry = 0
	goto	Interval_ok
	goto	Send_Heating

Interval_ok
	goto	Send_Off

;----------------------------------------------------------------
;Extra display procedures
;----------------------------------------------------------------

Send_Cooling
	call	Send_ClearScreen
	call	Send_Space
	call	Send_Space	;2
	call	Send_Space	;3
	call	Send_Space	;4
	call	Send_C		;5
	call	Send_o		;6
	call	Send_o		;7
	call	Send_l		;8

	call	Send_NextLine

	call	Send_i
	call	Send_n
	call	Send_g

	goto	main			

Send_Heating
	call	Send_ClearScreen
	call	Send_Space
	call	Send_Space	;2
	call	Send_Space	;3
	call	Send_Space	;4
	call	Send_H		;5
	call	Send_e		;6
	call	Send_a		;7
	call	Send_t		;8

	call	Send_NextLine

	call	Send_i
	call	Send_n
	call	Send_g

	goto	main			

Send_Off
	call	Send_ClearScreen
	call	Send_Space
	call	Send_Space	;2
	call	Send_Space	;3
	call	Send_Space	;4
	call	Send_Space	;4
	call	Send_Space	;4
	call	Send_O		;5
	call	Send_f		;6

	call	Send_NextLine

	call	Send_f

	goto	main			



;****************************************************************
;		Temperatuursregeling - Einde			
;****************************************************************


;---------------------------------------------------------------
;---------------------------------------------------------------
;Hoofdprogramma
;---------------------------------------------------------------
;---------------------------------------------------------------


main				;Probleem: Temp_Lo,2 wordt nooit = 1!!!!!!!!!!!!!!!!!

	;Temp lezen
	;bcf INTCON,GIE		;geen globale interrupts <=> Is dit nodig??????????
				;Ik denk het niet aangezien er al een interrupt mogelijk is door de klok 
				;Kan dit niet gewoon elke keer als het prog door de mainloop gaat, zonder naar de interrupt 

	call	TempRead	;Sensor initialiseren
	call	TempLoop
	;call	TempCCM

	;bsf INTCON,GIE		;enable globale interrupts

	;Is de temp conversie compleet? Als bit 2 van Temp_Lo = 1 is de conversie compleet
	btfss	Temp_Lo,2	;waarom skip if set? Om ervoor te zorgen dat er ook rekening wordt gehouden met het geval dat bit 2
	goto	main		;verschillend is van 1. In dit geval gaan we gewoon terug naar main

	movlw	B'00001111'	
	movwf	LCDData	
	;Laat de 3 LSB wegvallen (bit 0, 1 en 2), aangezien die niet mee de waarde van de temp bepalen
	bcf	STATUS,C	;Carry = 0
	rrf	Temp_Lo
	rrf	Temp_Hi
	bcf	STATUS,C	;Carry = 0
	rrf	Temp_Lo
	rrf	Temp_Hi
	bcf	STATUS,C	;Carry = 0
	rrf	Temp_Lo
	rrf	Temp_Hi

	;Negatieve temperatuur 
	btfsc	Temp_Hi,4		;als bit 4 = 1
	bsf	Sign,Flag_Signbit	;dan wordt Flag_Signbit = 1 => de temperatuur is negatief 
	btfss	Temp_Hi,4		;als bit 4 = 0
 	bcf	Sign,Flag_Signbit	;dan wordt Flag_Signbit = 0 => de temperatuur is positief
	
	btfss	Sign,Flag_Signbit	;Als Flag_Signbit = 0
	goto	main			;ga naar het volgende deel van het programma


	bsf	Temp_Hi,7	;Dit is omdat we werken met de 2's complement methode om binair een negatief getal weer te geven
	bsf	Temp_Hi,6
	bsf	Temp_Hi,5

	comf	Temp_Hi,F	;complement nemen
	comf	Temp_Lo,F	;complement nemen
	incf	Temp_Lo,F	;2 optellen, binair gezien
	btfsc	STATUS,C	;als Carry = 1, betekent dit dat de MSB van Temp_Lo + 1 buiten Temp_Lo valt
	incf	Temp_Hi,F	;moet bij het 2de register ook 1 bijgeteld worden

	;Actie van de thermostaat in functie van de afgelezen temp
	call	ControleMax


	goto	main
;++++++++++++++++++++++++++Einde+++++++++++++++++++++++++++++++++ 

	end