; INFOS :
; =======

; Gestion de T° et Temporisation pour couveuse à oeufs

; Fait par Aurélien ROBERT
; Web : http://www.aurelienr.com
; E-mail : aurelienr@hotmail.com

; Derniere version 06/2002

; DESCRIPTION :
; =============

; Gestion de 4 poussoirs, un afficheur LCD et un capteur de T° I²C
; Affichage sur ecran LCD 2 lignes 16 caracteres controllé par HD44780
; Key-debouncing par 74C922
; Capteur de temperature LM92 : I²C, 12 bits + signe, window comparator

; Le programme commande une resistance chauffante par "PWM" sur un signal de 1Hz
; Il utilise de valeurs pré-décidées en fonction de l'ecart de T° lue et T° consigne (T°c)
; Il enregistre chaque valeur de % utilisé, pour une temperature comprise entre T°c-1 et T°c+1
; Apres 128 valeurs il calcule la valeur moyenne et l'utilise en tant qu'equilibre = valeur PWM pour T°lue=T°c

; Gestion de 2 temporisations : T1, à  la seconde pres et T2, à la minute pres

; Pour tout cela on utilise un quartz de 18.4320 MHz (Tcy = 217ns) qui donne, avec Timer0 (en valeur 180) et prescaler max.,
; une interruption toutes les 10ms. Afin de creer le PWM directement...
; Une interruption toutes les : 10ms=(4x180x256)/18432000 avec 256 dans prescaler, 180 dans TMR0

; La temperature est lue dans le LM92 toute les secondes

; Affichage de la temperature en "direct" sur LCD
; 4 poussoirs MENU , OK , + , -
; Possibilité de programmer : T°c, T°min, T°max, T°hyst, T1, T2
; Etalonnage du capteur T°
; Sauvegarde en EEPROM des parametres utilisés
; Sorties alarmes pour T° excessives (apres definition de T°min et T°max)

; Le retro eclairage du LCD est commandé par le PIC


	list p=16f873
	include <P16F873.INC>

; Bits de Configuration, CF p16f873.inc :
; =======================================

	__CONFIG _BODEN_OFF & _CP_ALL & _PWRTE_ON & _WDT_OFF & _HS_OSC & _LVP_OFF & _WRT_ENABLE_ON

; Variables RAM :
; ===============

	cblock	0x020
		LCDTmp, Dv0, Dv1, Dv2, Dv3, DvTmp, DvTmp2		; variables LCD
		Taff_ent, Taff_virg			; variables LCD
		BCDix, BCUnit, BCTmp, BCCent, Compare		; variables Maths	
		donnee, var1, var2, var3, var4, bool		; variables EEPROM / I²C
		Tcons_ent, Tcons_virg, Tlue_ent, Tlue_virg		; variables Température
		offset_ent, offset_virg, diff, Ttmp1, Ttmp2		; variables Température
		Tmin_ent, Tmax_ent, Tmin_virg, Tmax_virg		; variables Température
		pwm, equil, nb_prel, sum_msb, sum_lsb, fsr_tmp	; variables PWM
		menu, ssmenu, Regl_Tmp, actif, Regl_Tmp_ent, Regl_Tmp_virg	; variables Menu
		Ton, Toff, PDel0, PDel1, PDel2		; variables Temps
		count_sec, count_msec, ton_used, toff_used		; variables Temps	
	endc
	
	cblock	0x060
		part2:32
	endc

	cblock	0x0A0
		part1:96
	endc

; Equates :
; =========

T_ADR_RD	EQU	B'10010111'	; adresse pour lecture
T_ADR_W	EQU	B'10010110'	; adresse pour ecriture
T_ADR_TEMP	EQU	B'00000000'	; registre temperature (read only)
T_ADR_CFG	EQU	B'00000001'	; registre configuration
T_ADR_HYST	EQU	B'00000010'	; registre T° hysteresis
T_ADR_MAX	EQU	B'00000101'	; registre T° max
T_ADR_MIN	EQU	B'00000100'	; registre T° min

T_HYST	EQU	B'01000000'	; 0.5°C hysteresis

IO_TRISA	EQU	B'00000111'
IO_TRISB	EQU	B'00000001'
IO_TRISC	EQU	B'00011000'

; Defines :
; =========

#DEFINE	LCD_RS	PORTB,1	; sortie selection RS (data-instruction) LCD
#DEFINE	LCD_RW	PORTB,2	; sortie selection Read-/Write
#DEFINE	LCD_E	PORTB,3	; sortie Enable
#DEFINE	BP_M	PORTA,0	; KEYPAD1
#DEFINE	BP_OK	PORTA,1	; KEYPAD2
#DEFINE	INT_T	PORTA,2	; alarme LM92 (active low)

#DEFINE	LED_O	PORTC,1	; LED orange
#DEFINE	LED_R	PORTC,2	; LED rouge

#DEFINE	LCD_RE	PORTC,5	; retro eclairage LCD
#DEFINE	OUT_AL	PORTA,3	; sortie alarme
#DEFINE	OUT_RC	PORTA,5	; vers triac (resistance chauffante)
#DEFINE	OUT_T	PORTC,0	; sortie de temporisation

#DEFINE	lue_sup	Compare,0	; lue_sup est à 1 si la température lue est supérieure à celle de la consigne
#DEFINE	offset_tmp	Compare,2	; à 1 si l'offset T° est positif
#DEFINE	hp	Compare,4	; à 1 si la température est hors-plage
#DEFINE	Alarme	Compare,5	; à 1 si la température est en dessous de Tmin ou au dessus de Tmax

#DEFINE	AckError	bool,1	; le bit Ack n'a pas été reçu
#DEFINE	AckBit	bool,2	; on doit envoyer le bit Stop

#DEFINE	menu_ok	menu,0	; le menu est activé
#DEFINE	menu_ss	menu,1	; on est dans le sous-menu, sinon on règle un paramètre
#DEFINE	menu_inc	menu,2
#DEFINE	menu_dec	menu,3
#DEFINE	menu_valid	menu,4
#DEFINE	menu_ma	ssmenu,0	; opt1
#DEFINE	menu_tcons	ssmenu,1	; opt2
#DEFINE	menu_ton	ssmenu,2	; opt3
#DEFINE	menu_toff	ssmenu,3	; opt4
#DEFINE	menu_tmin	ssmenu,4	; opt5
#DEFINE	menu_tmax	ssmenu,5	; opt6
#DEFINE	menu_etal	ssmenu,6	; opt7
#DEFINE	tempe_on	Regl_Tmp,0	; à 1 si temperature=1
#DEFINE	tempo_on	Regl_Tmp,1	; à 1 si tempo=1
#DEFINE	tempeON	actif,0	; à 1 si la gestion des températures est activée
#DEFINE	tempoON	actif,1	; à 1 si la gestion de temporisations est activée
#DEFINE	tonACTIF	actif,2	; à 1 si ton est en train d'être décrémenté
#DEFINE	toffACTIF	actif,3	; à 1 si toff est en train d'être décrémenté
#DEFINE	offset_pos	actif,4	; à 1 si l'offset est positif, 0 si négatif

; Macros
; ======

VALID	MACRO		; Enable Bit LCD
	bsf	LCD_E
	nop
	nop
	nop
	bcf	LCD_E
	ENDM

ASCII	MACRO		; transformer un chiffre en sa notation ASCII (w -> w)
	addlw	B'00110000'
	ENDM

BANK0	MACRO
	bcf	STATUS,RP0
	bcf	STATUS,RP1
	ENDM

BANK1	MACRO
	bsf	STATUS,RP0
	bcf	STATUS,RP1
	ENDM

;////////////////
;/ Reset Vector /
;////////////////

	org	0x00
	goto	start

;////////////////////
;/ Interrupt Vector /
;////////////////////
	
	org	0x04
	btfsc	INTCON,T0IF
	goto	int_timer
int_pad	bcf	INTCON,INTF
	btfsc	AckError
	goto	endpad
	bsf	LCD_RE
	clrf	PCLATH
	movf	PORTA,w
	andlw	B'00000011'
	addwf	PCL,f
	goto	bp_moins	; 00
	goto	bp_ok1	; 01
	goto	bp_plus	; 10
	goto	bp_menu	; 11

bp_menu	btfss	menu_ok
	goto	m_ma
	btfsc	menu_ss
	goto	endmenu	; on était dans un sous-menu donc on efface tout
	btfsc	menu_ma
	goto	m_ma
	btfsc	menu_tcons
	goto	m_tcons
	btfsc	menu_ton
	goto	m_ton
	btfsc	menu_toff
	goto	m_toff
	btfsc	menu_tmin
	goto	m_tmin
	btfsc	menu_tmax
	goto	m_tmax
	goto	m_etal

bp_ok1	btfss	menu_ok
	goto	endpad	; rien à valider !
	btfss	menu_ss
	goto	save_param	; paramètre à sauvegarder
	btfsc	menu_ma
	goto	regle_ma
	btfsc	menu_tcons
	goto	regle_tcons
	btfsc	menu_ton
	goto	regle_ton
	btfsc	menu_toff
	goto	regle_toff
	btfsc	menu_tmin
	goto	regle_tmin
	btfsc	menu_tmax
	goto	regle_tmax
	goto	regle_etal

bp_plus	btfss	menu_ok
	goto	endpad	; rien à valider !
	btfss	menu_ss
	goto	inc_param	; paramètre à incrémenter
	btfsc	menu_ma
	goto	m_tcons
	btfsc	menu_tcons
	goto	m_ton
	btfsc	menu_ton
	goto	m_toff
	btfsc	menu_toff
	goto	m_tmin
	btfsc	menu_tmin
	goto	m_tmax
	btfsc	menu_tmax
	goto	m_etal
	goto	endpad	; bloqué

bp_moins	btfss	menu_ok
	goto	endpad	; rien à valider !
	btfss	menu_ss
	goto	dec_param
	btfsc	menu_etal
	goto	m_tmax
	btfsc	menu_tmax
	goto	m_tmin
	btfsc	menu_tmin
	goto	m_toff
	btfsc	menu_toff
	goto	m_ton
	btfsc	menu_ton
	goto	m_tcons
	btfsc	menu_tcons
	goto	m_ma
	goto	endpad	; bloqué

m_ma	call	ClrDisp	; affiche le sous_menu de réglage Marche/Arret
	bsf	menu_ok
	bsf	menu_ss
	clrf	ssmenu
	bsf	menu_ma
	movlw	D'1'
	movwf	var4
	call	AffOptn	; affichage de Option 1
	call	Fleche_D
	movlw	B'11000000'
	call	SendCmd
	movlw	0x83
	movwf	var1
	movlw	D'12'
	movwf	var3
	call	AffMsg
	goto	endpad

m_tcons	call	ClrDisp	; affiche le sous_menu de réglage T°consigne
	bsf	menu_ok
	bsf	menu_ss
	clrf	ssmenu
	bsf	menu_tcons
	movlw	D'2'
	movwf	var4
	call	AffOptn	; affichage
	call	Fleche_D
	call	Fleche_G
	call	AffRegl
	movlw	0x8F
	movwf	var1
	movlw	D'6'
	movwf	var3
	call	AffMsg
	goto	endpad

m_ton	call	ClrDisp	; affiche le sous_menu de réglage Ton
	bsf	menu_ok
	bsf	menu_ss
	clrf	ssmenu
	bsf	menu_ton
	movlw	D'3'
	movwf	var4
	call	AffOptn
	call	Fleche_D
	call	Fleche_G
	call	AffRegl
	movlw	'T'	; plus rapide à afficher comme ça
	call	SendData
	movlw	'o'
	call	SendData
	movlw	'n'
	call	SendData
	goto	endpad

m_toff	call	ClrDisp	; affiche le sous_menu de réglage Toff
	bsf	menu_ok
	bsf	menu_ss
	clrf	ssmenu
	bsf	menu_toff
	movlw	D'4'
	movwf	var4
	call	AffOptn	; affichage
	call	Fleche_D
	call	Fleche_G
	call	AffRegl
	movlw	'T'
	call	SendData
	movlw	'o'
	call	SendData
	movlw	'f'
	call	SendData
	movlw	'f'
	call	SendData
	goto	endpad

m_tmin	call	ClrDisp	; affiche le sous_menu de réglage T°min
	bsf	menu_ok
	bsf	menu_ss
	clrf	ssmenu
	bsf	menu_tmin
	movlw	D'5'
	movwf	var4
	call	AffOptn	; affichage
	call	Fleche_D
	call	Fleche_G
	call	AffRegl
	movlw	0x53
	movwf	var1
	movlw	D'5'
	movwf	var3
	call	AffMsg
	goto	endpad

m_tmax	call	ClrDisp	; affiche le sous_menu de réglage T°max
	bsf	menu_ok
	bsf	menu_ss
	clrf	ssmenu
	bsf	menu_tmax
	movlw	D'6'
	movwf	var4
	call	AffOptn	; affichage
	call	Fleche_D
	call	Fleche_G
	call	AffRegl
	movlw	0x5D
	movwf	var1
	movlw	D'5'
	movwf	var3
	call	AffMsg
	goto	endpad

m_etal	call	ClrDisp	; affiche le sous_menu de Etalonnage
	bsf	menu_ok
	bsf	menu_ss
	clrf	ssmenu
	bsf	menu_etal
	movlw	D'7'
	movwf	var4
	call	AffOptn	; affichage
	call	Fleche_G
	movlw	B'11000000'
	call	SendCmd
	movlw	0x95
	movwf	var1
	movlw	D'10'
	movwf	var3
	call	AffMsg
	goto	endpad

save_param	bsf	menu_valid
	goto	where
inc_param	bsf	menu_inc
	goto	where
dec_param	bsf	menu_dec	
where	btfsc	menu_ma
	goto	regle_ma
	btfsc	menu_tcons
	goto	regle_tcons
	btfsc	menu_ton
	goto	regle_ton
	btfsc	menu_toff
	goto	regle_toff
	btfsc	menu_tmin
	goto	regle_tmin
	btfsc	menu_tmax
	goto	regle_tmax
	goto	regle_etal

regle_ma	btfsc	menu_inc
	goto	inc_ma
	btfsc	menu_dec
	goto	dec_ma
	btfsc	menu_valid
	goto	save_ma
	bcf	menu_ss
	movf	actif,w	; on charge la valeur d'origine dans une variable temporaire
	movwf	Regl_Tmp
	call	ClrDisp
	movlw	B'10000000'
	call	SendCmd
	movlw	0x13
	movwf	var1
	movlw	D'10'
	movwf	var3
	call	AffMsg
	movlw	0xA5
	movwf	var1
	movlw	D'3'
	movwf	var3
	call	AffMsg
	movlw	B'11000000'
	call	SendCmd
	movlw	0x9F
	movwf	var1
	movlw	D'9'
	movwf	var3
	call	AffMsg
	goto	aff_ma
inc_ma	bcf	menu_inc
	btfsc	tempe_on
	goto	$+3
	bsf	tempe_on
	goto	aff_ma
	bcf	tempe_on
	goto	aff_ma
dec_ma	bcf	menu_dec
	btfsc	tempo_on
	goto	$+3
	bsf	tempo_on
	goto	aff_ma
	bcf	tempo_on
aff_ma	movlw	B'10001101'
	call	SendCmd
	btfsc	tempe_on	
	call	Aff_ON
	btfss	tempe_on
	call	Aff_OFF
	movlw	B'11001101'
	call	SendCmd
	btfsc	tempo_on
	call	Aff_ON
	btfss	tempo_on
	call	Aff_OFF
	goto	endpad
save_ma	movf	Regl_Tmp,w
	movwf	actif	; on garde la nouvelle valeur pour utilisation dès maintenant
	movwf	donnee
	movlw	0x2A
	call	WriteEE
	btfss	tempeON
	bcf	OUT_AL
	goto	endmenu
	
regle_ton	btfsc	menu_inc
	goto	inc_ton
	btfsc	menu_dec
	goto	dec_ton
	btfsc	menu_valid
	goto	save_ton
	bcf	menu_ss
	call	ClrDisp
	movf	Ton,w
	movwf	Regl_Tmp
	movlw	B'10000000'
	call	SendCmd
	movlw	0x3E
	movwf	var1
	movlw	D'10'
	movwf	var3
	call	AffMsg
	goto	aff_ton
inc_ton	bcf	menu_inc
	incf	Regl_Tmp,f
	goto	aff_ton
dec_ton	bcf	menu_dec
	decf	Regl_Tmp,f
aff_ton	movlw	B'11000000'
	call	SendCmd
	movf	Regl_Tmp,w
	call	BCD3
	movf	BCCent,w
	ASCII
	call	SendData
	movf	BCDix,w
	ASCII
	call	SendData
	movf	BCUnit,w
	ASCII
	call	SendData
	movlw	' '
	call	SendData
	movlw	's'
	call	SendData
	movlw	'e'
	call	SendData
	movlw	'c'
	call	SendData
	movlw	B'00101110'
	call	SendData
	goto	endpad
save_ton	movf	Regl_Tmp,w
	movwf	Ton
	movwf	ton_used
	movwf	donnee
	movlw	0x28
	call	WriteEE
	goto	endmenu

regle_toff	btfsc	menu_inc
	goto	inc_toff
	btfsc	menu_dec
	goto	dec_toff
	btfsc	menu_valid
	goto	save_toff
	bcf	menu_ss
	call	ClrDisp
	movf	Toff,w
	movwf	Regl_Tmp
	movlw	B'10000000'
	call	SendCmd
	movlw	0x48
	movwf	var1
	movlw	D'11'
	movwf	var3
	call	AffMsg
	goto	aff_toff
inc_toff	bcf	menu_inc
	incf	Regl_Tmp,f
	goto	aff_toff
dec_toff	bcf	menu_dec
	decf	Regl_Tmp,f
aff_toff	movlw	B'11000000'
	call	SendCmd
	movf	Regl_Tmp,w
	call	BCD3
	movf	BCCent,w
	ASCII
	call	SendData
	movf	BCDix,w
	ASCII
	call	SendData
	movf	BCUnit,w
	ASCII
	call	SendData
	movlw	' '
	call	SendData
	movlw	'm'
	call	SendData
	movlw	'i'
	call	SendData
	movlw	'n'
	call	SendData
	movlw	B'00101110'
	call	SendData
	goto	endpad
save_toff	movf	Regl_Tmp,w
	movwf	Toff
	movwf	toff_used
	movwf	donnee
	movlw	0x29
	call	WriteEE
	goto	endmenu

regle_tcons	btfsc	menu_inc
	goto	inc_tcons
	btfsc	menu_dec
	goto	dec_tcons
	btfsc	menu_valid
	goto	save_tcons
	bcf	menu_ss
	movf	Tcons_ent,w
	movwf	Regl_Tmp_ent
	movf	Tcons_virg,w
	movwf	Regl_Tmp_virg
	call	ClrDisp
	movlw	B'10000000'
	call	SendCmd
	movlw	0x2E
	movwf	var1
	movlw	D'16'
	movwf	var3
	call	AffMsg
	goto	aff_tcons
inc_tcons	bcf	menu_inc
	incf	Regl_Tmp_virg,f
	incf	Regl_Tmp_virg,f
	btfss	Regl_Tmp_virg,4
	goto	aff_tcons
	clrf	Regl_Tmp_virg
	incf	Regl_Tmp_ent,f
	goto	aff_tcons
dec_tcons	bcf	menu_dec
	decf	Regl_Tmp_virg,f
	decf	Regl_Tmp_virg,f
	btfss	Regl_Tmp_virg,7
	goto	aff_tcons
	movlw	B'00001110'
	movwf	Regl_Tmp_virg
	decf	Regl_Tmp_ent,f	
aff_tcons	movlw	B'11000000'
	call	SendCmd
	movf	Regl_Tmp_ent,w
	movwf	Taff_ent
	movf	Regl_Tmp_virg,w
	movwf	Taff_virg	
	call	Taffich
	goto	endpad
save_tcons	movf	Regl_Tmp_ent,w
	movwf	Tcons_ent
	movwf	donnee
	movlw	0x20
	call	WriteEE
	movf	Regl_Tmp_virg,w
	movwf	Tcons_virg
	movwf	donnee
	movlw	0x21
	call	WriteEE
	goto	endmenu	

regle_tmin	btfsc	menu_inc
	goto	inc_tmin
	btfsc	menu_dec
	goto	dec_tmin
	btfsc	menu_valid
	goto	save_tmin
	bcf	menu_ss
	movf	Tmin_ent,w
	movwf	Regl_Tmp_ent
	movf	Tmin_virg,w
	movwf	Regl_Tmp_virg
	call	ClrDisp
	movlw	B'10000000'
	call	SendCmd
	movlw	0x53
	movwf	var1
	movlw	D'10'
	movwf	var3
	call	AffMsg
	goto	aff_tmin
inc_tmin	bcf	menu_inc
	movlw	D'4'
	addwf	Regl_Tmp_virg,f
	btfss	Regl_Tmp_virg,4
	goto	aff_tmin
	clrf	Regl_Tmp_virg
	incf	Regl_Tmp_ent,f
	goto	aff_tmin
dec_tmin	bcf	menu_dec
	movlw	D'4'
	subwf	Regl_Tmp_virg,f	
	btfss	Regl_Tmp_virg,7
	goto	aff_tmin
	movlw	B'00001100'
	movwf	Regl_Tmp_virg
	decf	Regl_Tmp_ent,f	
aff_tmin	movlw	B'11000000'
	call	SendCmd
	movf	Regl_Tmp_ent,w
	movwf	Taff_ent
	movf	Regl_Tmp_virg,w
	movwf	Taff_virg	
	call	Taffich
	goto	endpad
save_tmin	movf	Regl_Tmp_ent,w
	movwf	Tmin_ent
	movwf	donnee
	movlw	0x22
	call	WriteEE
	movf	Regl_Tmp_virg,w
	movwf	Tmin_virg
	movwf	donnee
	movlw	0x23
	call	WriteEE
	call	Wr_Tmin
	goto	endmenu

regle_tmax	btfsc	menu_inc
	goto	inc_tmax
	btfsc	menu_dec
	goto	dec_tmax
	btfsc	menu_valid
	goto	save_tmax
	bcf	menu_ss
	movf	Tmax_ent,w
	movwf	Regl_Tmp_ent
	movf	Tmax_virg,w
	movwf	Regl_Tmp_virg
	call	ClrDisp
	movlw	B'10000000'
	call	SendCmd
	movlw	0x5D
	movwf	var1
	movlw	D'10'
	movwf	var3
	call	AffMsg
	goto	aff_tmax
inc_tmax	bcf	menu_inc
	movlw	D'4'
	addwf	Regl_Tmp_virg,f
	btfss	Regl_Tmp_virg,4
	goto	aff_tmax
	clrf	Regl_Tmp_virg
	incf	Regl_Tmp_ent,f
	goto	aff_tmax
dec_tmax	bcf	menu_dec
	movlw	D'4'
	subwf	Regl_Tmp_virg,f
	btfss	Regl_Tmp_virg,7
	goto	aff_tmax
	movlw	B'00001100'
	movwf	Regl_Tmp_virg
	decf	Regl_Tmp_ent,f	
aff_tmax	movlw	B'11000000'
	call	SendCmd
	movf	Regl_Tmp_ent,w
	movwf	Taff_ent
	movf	Regl_Tmp_virg,w
	movwf	Taff_virg	
	call	Taffich
	goto	endpad
save_tmax	movf	Regl_Tmp_ent,w
	movwf	Tmax_ent
	movwf	donnee
	movlw	0x24
	call	WriteEE
	movf	Regl_Tmp_virg,w
	movwf	Tmax_virg
	movwf	donnee
	movlw	0x25
	call	WriteEE
	call	Wr_Tmax
	goto	endmenu

regle_etal	btfsc	menu_inc
	goto	inc_etal
	btfsc	menu_dec
	goto	dec_etal
	btfsc	menu_valid
	goto	save_etal
	bcf	menu_ss
	movf	offset_ent,w
	movwf	Regl_Tmp_ent
	movf	offset_virg,w
	movwf	Regl_Tmp_virg
	bcf	offset_tmp
	btfsc	offset_pos
	bsf	offset_tmp	; copie du bit de signe
	call	ClrDisp
	movlw	B'10000000'
	call	SendCmd
	movlw	0x95		; affichage "etalonnage"
	movwf	var1
	movlw	D'10'
	movwf	var3
	call	AffMsg
	goto	aff_etal
inc_etal	bcf	menu_inc
	btfss	offset_tmp
	goto	inc_neg
	incf	Regl_Tmp_virg,f
	btfss	Regl_Tmp_virg,4	; dépassement ?
	goto	aff_etal		; l'incrémentation est effectuée
	clrf	Regl_Tmp_virg
	incf	Regl_Tmp_ent,f
	goto	aff_etal
inc_neg	decfsz	Regl_Tmp_virg,f
	goto	cont_neg
	movf	Regl_Tmp_ent,f
	btfss	STATUS,Z
	goto	cont_neg
	bsf	offset_tmp	; 0 est positif ici
	goto	aff_etal
cont_neg	btfss	Regl_Tmp_virg,7
	goto	aff_etal
	movlw	B'00001111'
	movwf	Regl_Tmp_virg
	decfsz	Regl_Tmp_ent,f
	goto	aff_etal
dec_etal	bcf	menu_dec
	btfss	offset_tmp
	goto	dec_neg
	decf	Regl_Tmp_virg,f
	btfss	Regl_Tmp_virg,7
	goto	aff_etal
	movf	Regl_Tmp_ent,f
	btfss	STATUS,Z
	goto	cont_pos
	movlw	0x01
	movwf	Regl_Tmp_virg
	bcf	offset_tmp
	goto	aff_etal
cont_pos	movlw	B'00001111'
	movwf	Regl_Tmp_virg
	decf	Regl_Tmp_ent,f
	goto	aff_etal
dec_neg	incf	Regl_Tmp_virg,f
	btfss	Regl_Tmp_virg,4
	goto	aff_etal
	clrf	Regl_Tmp_virg
	incf	Regl_Tmp_ent,f
aff_etal	movlw	B'11000000'
	call	SendCmd
	call	Rd_Temp
	call	ConvLMT
	movf	Tlue_virg,w
	movwf	Taff_virg
	movf	Tlue_ent,w
	movwf	Taff_ent
	btfss	offset_tmp		; Procédure qui ajoute/enlève l'offset à la température 
	goto	negofst1
	movf	Regl_Tmp_ent,w
	addwf	Taff_ent,f
	movf	Regl_Tmp_virg,w
	addwf	Taff_virg,f
	btfss	Taff_virg,4		; si ça a dépassé les 4 bits
	goto	affich_etal		; ça n'a pas dépassé les 4 bits possibles dont c'est bon
	movlw	B'00010000'
	subwf	Taff_virg,f	; on enleve la partie entière de Tlue_virg
	incf	Taff_ent,f	; on incrémente Tlue_ent
	goto	affich_etal
negofst1	movf	Regl_Tmp_ent,w
	subwf	Taff_ent,f
	movf	Regl_Tmp_virg,w
	subwf	Taff_virg,f
	btfsc	STATUS,Z
	goto	affich_etal	; c'est bon le resultat est 0 pour la virgule
	btfsc	STATUS,C
	goto	affich_etal	; c'est bon le resultat est >0
	decf	Taff_ent,f	; on décrémente Tlue_ent
	movf	Taff_virg,w
	subwf	Regl_Tmp_virg,w	; offset_virg - Tlue_virg -> w
	sublw	B'00010000'		; 10000 - w
	movwf	Taff_virg
affich_etal	call	Taffich
	goto	endpad
save_etal	movf	Regl_Tmp_ent,w
	movwf	offset_ent
	movwf	donnee
	movlw	0x26
	call	WriteEE
	movf	Regl_Tmp_virg,w
	movwf	offset_virg
	movwf	donnee
	movlw	0x27
	call	WriteEE
	bcf	offset_pos
	btfsc	offset_tmp
	bsf	offset_pos
	movf	actif,w
	movwf	donnee
	movlw	0x2A
	call	WriteEE		; sauvegarde du signe de l'offset dans l'EEPROM
	goto	endmenu

int_timer	bcf	INTCON,T0IF
	movlw	D'75'
	addwf	TMR0,f	; le timer ne doit avoir que 180 pas à incrémenter
	BANK1
	movlw	B'11000111'
	movwf	OPTION_REG
	BANK0	
	btfsc	AckError
	goto	wh_tempo
	btfss	tempeON
	goto	wh_tempo
	movf	pwm,f
	btfsc	STATUS,Z
	goto	$+4	; si à 0 on désactive la resistance
	decf	pwm,f	; on active la résistance chauffante
	bsf	OUT_RC
	goto	$+2
	bcf	OUT_RC	
wh_tempo	decfsz	count_msec,f	; où en est-on dans le temps...
	goto	test99		; on va tester si on a un calcul ou un affichage à faire
	movlw	D'100'		; une seconde est écoulée
	movwf	count_msec		; on remet à 100 count_msec pour la prochaine interruption
	decfsz	count_sec,f		; on décrémente le nbe de secondes
	goto	test_ton
	movlw	D'60'		; une minute est écoulée
	movwf	count_sec		; on remet à 60 count_min pour la prochaine interruption
	btfss	tempoON		; on regarde si on doit gerer les temporisations
	goto	new_temp
	btfss	toffACTIF		; est ce que toff est en action
	goto	test_ton		; non donc on va verifier ton...
	bcf	OUT_T		; on désactive la sortie relais
	decfsz	toff_used,f		; on décrémente le nbe de minutes de Toff
	goto	new_temp		; pas à zéro, on quitte les tempos
	bcf	toffACTIF		; toff est terminé, c'est ton qui est activé
	bsf	tonACTIF
	movf	Toff,w
	movwf	toff_used		; on recharge toff pour la prochaine fois
test_ton	btfss	tonACTIF
	goto	new_temp
	btfss	tempoON
	goto	new_temp
	bsf	OUT_T		; on active la sortie relais
	decfsz	ton_used,f
	goto	new_temp
	bcf	OUT_T		; on repasse en toff actif
	bcf	tonACTIF
	bsf	toffACTIF
	movf	Ton,w
	movwf	ton_used		; on recharge ton pour la prochaine fois
new_temp	call	Rd_Temp
	call	ConvLMT		; conversion pour utilisation en calcul
	call	Toffset		; ajoute l'offset à la température lue
	goto	endtimer
test99	movlw	D'99'
	subwf	count_msec,w	; sommes nous 10ms plus tard après avoir lu ??
	btfss	STATUS,Z
	goto	test98		; et non..
	call	Ecart		; retourne dans diff l'écart entre (Tlue+Offset) et Tcons
	movf	diff,f
	btfsc	STATUS,Z
	goto	nochange
	btfss	lue_sup		
	goto	inc_equil		; on va augmenter l'equilibre pour que la température monte
	movlw	0x06		; Tlue > Tcons ! (difference > 0) : on baisse l'equilibre
	subwf	diff,w
	btfsc	STATUS,Z
	goto	$+3
	btfss	STATUS,C
	goto	test_diff6
	clrw
	goto	ok_equil
test_diff6	movlw	0x07
	movwf	PCLATH
	movf	diff,w
	andlw	B'00000111'
	addlw	D'32'
	call	tableau	; on va rechercher la valeur dans le tableau
	subwf	equil,w	; equil - pourcentage lu
	btfss	STATUS,C	; test de Carry apres equil - pourcentage / si C=1, c'est bon sinon RAZ
	clrw		; C=0 donc pwm < 0 donc on le remet à zéro
	goto	ok_equil	; on enregistre w dans PWM	

inc_equil	movlw	0x50	; test ent>5 ?
	subwf	diff,w	; diff - 5
	btfsc	STATUS,Z
	goto	$+3
	btfss	STATUS,C	; si C=1 diff > 5
	goto	test_diff1
	movlw	D'100'
	goto	ok_equil
test_diff1	movlw	0x40
	subwf	diff,w
	btfsc	STATUS,Z
	goto	$+3
	btfss	STATUS,C	; C=1 => diff > 4
	goto	test_diff2
	movlw	D'90'
	goto	ok_equil
test_diff2	movlw	0x30
	subwf	diff,w
	btfsc	STATUS,Z
	goto	$+3
	btfss	STATUS,C
	goto	test_diff3
	movlw	D'80'
	goto	ok_equil
test_diff3	movlw	0x20
	subwf	diff,w
	btfsc	STATUS,Z
	goto	$+3
	btfss	STATUS,C
	goto	test_diff4
	movlw	D'70'
	goto	ok_equil
test_diff4	movlw	0x09
	subwf	diff,w
	btfsc	STATUS,Z
	goto	$+3
	btfss	STATUS,C
	goto	test_diff5
	movlw	D'60'
	goto	ok_equil
test_diff5	movlw	0x07
	movwf	PCLATH
	movf	diff,w
	andlw	B'00000111'	; filtre au cas où...
	addlw	D'37'
	call	tableau	; on vas chercher dans le tableau la valeur correspondante
	addwf	equil,w
	movwf	pwm
	movlw	D'100'
	subwf	pwm,w	; pwm - 100
	btfss	STATUS,C	; C=1 => pwm > 100
	goto	$+3
	movlw	D'100'	; maximum à 100 %	
ok_equil	movwf	pwm	; enregistrement dans PWM
	call	Save_Equil	; enregistrement du nouvel equilibre
	btfss	LED_O
	goto	$+3
	bcf	LED_O
	goto	endtimer
	bsf	LED_O
	goto	endtimer	
nochange	movf	equil,w		; l'equilibre n'a pas besoin d'être modifié
	movwf	pwm
	call	Save_Equil	; va sauvegarder l'equilibre et calculer eventuellement le nouveau
	goto	endtimer

test98	movlw	D'98'
	subwf	count_msec,w
	btfss	STATUS,Z
	goto	endtimer
	btfsc	menu_ok
	goto	endtimer	; le menu est activé donc on n'affiche pas la température
	btfsc	AckError
	goto	endtimer	; il y a une erreur de connection avec le capteur, on garde l'ecran d'erreur
	call	ClrDisp	
	clrf	var1
	movlw	D'11'
	movwf	var3
	call	AffMsg
	movlw	' '
	call	SendData
	movlw	B'00111010'
	call	SendData
	movlw	B'11000000'
	call	SendCmd
	movf	Tlue_ent,w
	movwf	Taff_ent
	movf	Tlue_virg,w
	movwf	Taff_virg
	call	Taffich
	goto	endtimer
endmenu	clrf	menu	; effacement des variables booléennes : on repasse en affichage de température
	clrf	ssmenu
	bcf	LCD_RE
	call	ClrDisp
endpad	btfsc	INTCON,T0IF
	goto	int_timer
	bcf	INTCON,INTF
	goto	restore
endtimer	btfsc	INTCON,INTF
	goto	int_pad
	bcf	INTCON,T0IF
restore	retfie

;///////////////////////
;/ Programme principal /
;///////////////////////

start	BANK1
	movlw	0x06
	movwf	ADCON1	; not PORTA as analog input
	movlw	IO_TRISA
	movwf	TRISA
	movlw	IO_TRISB
	movwf	TRISB
	movlw	IO_TRISC
	movwf	TRISC
	BANK0
	clrf	PORTC
	clrf	PORTB
	clrf	PORTA
	movlw	0x20	; initialisation RAM des 2 banques
	movwf	FSR
init_ram1	clrf	INDF
	incf	FSR,f
	btfss	FSR,7	; dès que ça atteint 0x80 (la ram1 s'arrete à 0x7F)
	goto	init_ram1
	movlw	0xA0
	movwf	FSR
init_ram2	clrf	INDF
	incf	FSR,f
	btfsc	FSR,7	; apres avoir atteint 0xFF (ça commence à 0xA0) on incremente FSR et donc FSR,7=0
	goto	init_ram2
	call	T5m	; attente 20ms
	call	T5m
	call	T5m
	call	T5m
	movlw	B'00110000'	; procédure d'initialisation LCD
	movwf	PORTB	
	VALID		
	call	T5m	; attente 5ms
	VALID
	call	T100u	; attente 100us
	VALID
	call	T100u	; attente 100us
	movlw	B'00100000'	; mode 4 bits
	movwf	PORTB
	VALID
	call	T5m
	movlw	H'01'	;Effacement
	call	SendCmd
	call	T5m
	movlw	H'28'	;Config 2 lignes
	call	SendCmd
	movlw	H'0C'	;Contrôle affichage
	call	SendCmd
	movlw	H'06'	;Déplacement
	call	SendCmd
	movlw	H'02'	;Retour en début de première ligne
	call	SendCmd
	call	T5m	
	movlw	B'10000100'	; Affichage message intro
	call	SendCmd
	movlw	0x0B
	movwf	var1
	movlw	D'8'
	movwf	var3
	call	AffMsg
	movlw	B'11000011'		
	call	SendCmd
	movlw	0x13
	movwf	var1
	movlw	D'10'
	movwf	var3
	call	AffMsg
	movlw	0x20	; récupération des infos en EEPROM
	call	ReadEE
	movwf	Tcons_ent
	movlw	0x21
	call	ReadEE
	movwf	Tcons_virg
	movlw	0x22
	call	ReadEE
	movwf	Tmin_ent
	movlw	0x23
	call	ReadEE
	movwf	Tmin_virg
	movlw	0x24
	call	ReadEE
	movwf	Tmax_ent
	movlw	0x25
	call	ReadEE
	movwf	Tmax_virg
	movlw	0x26
	call	ReadEE
	movwf	offset_ent
	movlw	0x27
	call	ReadEE
	movwf	offset_virg
	movlw	0x28
	call	ReadEE
	movwf	Ton
	movwf	ton_used
	movlw	0x29
	call	ReadEE
	movwf	Toff
	movwf	toff_used
	movlw	0x2A
	call	ReadEE
	movwf	actif
	movlw	0x2B
	call	ReadEE
	movwf	equil
	BANK1
	bsf	SSPSTAT,SMP		; I2C slew rate control disabled
	BANK0
	bsf	SSPCON,SSPM3	; I2C master mode in hardware
	bsf	SSPCON,SSPEN	; enable SSP module
	BANK1
	movlw	D'40'		; set I2C clock rate to 110kHz
	movwf	SSPADD
	BANK0
	call	Wr_Thyst		; chargement des valeurs dans les registres du LM92
	call	Wr_Tmax
	call	Wr_Tmin
	call	Rd_Temp		; on commence une lecture du LM92 qui ne sera pas prise en compte
	movlw	D'200'
	movwf	var1
intro	call	T5m	; attente d'une seconde
	decfsz	var1,f
	goto	intro
	movlw	D'100'	; initialisation variables tempos
	movwf	count_msec
	movlw	D'60'
	movwf	count_sec
	movlw	D'128'
	movwf	nb_prel	; nombre d'enregistrements de valeur moyennes
	movlw	0x60
	movwf	fsr_tmp	; adresse pour le 1er enregistrement d'équilibre
	bsf	toffACTIF
	bcf	tonACTIF
	movlw	D'75'
	movwf	TMR0
	BANK1
	movlw	B'11000111'
	movwf	OPTION_REG
	BANK0
	movlw	B'10110000'	; timer0 et rb0
	movwf	INTCON	; active les interruptions
loop	btfss	tempeON
	goto	loop
	btfsc	Alarme
	goto	set_alarm
	bcf	OUT_AL
	goto	loop
set_alarm	bsf	OUT_AL
	goto	loop

; Routines de temporisation
; =========================

T5m	movlw	D'66'	; 5ms
	movwf	PDel0
PLoop1	movlw	D'69'
	movwf	PDel1
PLoop2	clrwdt
	clrwdt
	decfsz	PDel1,f
	goto	PLoop2
	decfsz	PDel0,f
	goto	PLoop1
	clrwdt
	return
	
T100u	movlw	D'114'	; 100µs
	movwf	PDel0
PLoop0	clrwdt
	decfsz	PDel0,f
	goto	PLoop0
	return

; Routines I²C
; ============

I2C_Start1	BANK1			; envoie un bit de Start
	bsf	SSPCON2,SEN
	btfsc	SSPCON2,SEN
	goto	$-1
	BANK0
	return

I2C_ReStart	BANK1			; envoie un bit de Repeated Start
	bsf	SSPCON2,RSEN
	btfsc	SSPCON2,RSEN
	goto	$-1
	BANK0
	return

I2C_Stop1	BANK1			; envoie un bit de Stop
	bsf	SSPCON2,PEN
	btfsc	SSPCON2,PEN
	goto	$-1
	BANK0
	return

I2C_Send	bcf	PIR1,SSPIF		; envoie un Octet au composant, attente d'Ack sinon ecran d'erreur
	nop			; donnee à envoyer contenue dans w
	movwf	SSPBUF
	movwf	donnee
	btfss	PIR1,SSPIF
	goto	$-1
	BANK1
	nop
	nop
	nop
	nop	
	nop
	nop	
	nop
	nop
	btfss	SSPCON2,ACKSTAT
	goto	reçu
	BANK0
	btfsc	AckError
	goto	retry
	bsf	AckError	; le clavier ne fonctionnera pas
	swapf	actif,f	; on passe en config IDLE
	call	ClrDisp
	movlw	0xA8
	movwf	var1
	movlw	D'11'
	movwf	var3
	call	AffMsg
	movlw	B'11000000'
	call	SendCmd
	movlw	0xB3
	movwf	var1
	movlw	D'8'
	movwf	var3
	call	AffMsg
retry	BANK1
	bsf	SSPCON2,RSEN
	btfsc	SSPCON2,RSEN
	goto	$-2
	BANK0
	movf	donnee,w
	goto	I2C_Send
reçu	BANK0
	btfss	AckError
	return
	swapf	actif,f	; on se remet en config precedente
	bcf	AckError
	return

I2C_Receive	bcf	PIR1,SSPIF		; reçoit un Octet du composant
	BANK1
	bsf	SSPCON2,RCEN
	BANK0
	btfss	PIR1,SSPIF		; octet reçu ?
	goto	$-1
	movf	SSPBUF,w
	movwf	donnee
	btfsc	AckBit
	goto	send_ack
	BANK1
	bsf	SSPCON2,ACKDT	; NoAck
	bsf	SSPCON2,ACKEN
	btfsc	SSPCON2,ACKEN
	goto	$-1
	BANK0
	return
send_ack	BANK1
	bcf	SSPCON2,ACKDT
	bsf	SSPCON2,ACKEN
	btfsc	SSPCON2,ACKEN
	goto	$-1
	bcf	SSPCON2,RCEN	; disable receive mode
	BANK0
	return

Wr_Thyst	call	I2C_Start1		; charge la valeur de Thyst dans le LM92
	movlw	T_ADR_W
	call	I2C_Send
	movlw	T_ADR_HYST
	call	I2C_Send
	clrw
	call	I2C_Send
	movlw	T_HYST
	call	I2C_Send
	call	I2C_Stop1
	return

Wr_Tmax	movf	Tmax_ent,w
	movwf	Ttmp2
	movf	Tmax_virg,w
	movwf	Ttmp1
	call	ConvTLM
	call	I2C_Start1		; charge la valeur de T°max
	movlw	T_ADR_W
	call	I2C_Send	
	movlw	T_ADR_MAX
	call	I2C_Send
	movf	Ttmp2,w
	call	I2C_Send
	movf	Ttmp1,w
	call	I2C_Send
	call	I2C_Stop1
	return
	
Wr_Tmin	movf	Tmin_ent,w
	movwf	Ttmp2
	movf	Tmin_virg,w
	movwf	Ttmp1
	call	ConvTLM
	call	I2C_Start1		; charge la valeur de T°min
	movlw	T_ADR_W
	call	I2C_Send	
	movlw	T_ADR_MIN
	call	I2C_Send
	movf	Ttmp2,w
	call	I2C_Send
	movf	Ttmp1,w
	call	I2C_Send
	call	I2C_Stop1
	return

Rd_Temp	call	I2C_Start1
	movlw	T_ADR_W
	call	I2C_Send
	movlw	T_ADR_TEMP
	call	I2C_Send
	call	I2C_ReStart
	movlw	T_ADR_RD
	call	I2C_Send
	bsf	AckBit
	call	I2C_Receive
	movf	donnee,w
	movwf	Tlue_ent
	bcf	AckBit
	call	I2C_Receive
	call	I2C_Stop1
	movf	donnee,w
	movwf	Tlue_virg
	bcf	Alarme
	btfsc	Tlue_virg,0
	bsf	Alarme
	btfsc	Tlue_virg,1
	bsf	Alarme	
	return	

; Routines mathématiques
; ======================

BCD3	movwf	BCTmp	; Conversion Binaire en 3 Digits 000-255
	clrf	BCCent
BCD31	movlw	D'100'
	subwf	BCTmp,f
	btfss	STATUS,Z
	goto	$+3
	incf	BCCent,f
	return
	btfss	STATUS,C
	goto	BCDa
	incf	BCCent,f
	goto	BCD31
BCDa	movlw	D'100'
	addwf	BCTmp,w	
BCD	movwf	BCTmp	; Conversion Binaire en 2 Digits 00-99
	clrf	BCDix	
	clrf	BCUnit
BCD1	movlw	D'10'
	subwf	BCTmp,f	; BCTmp - 10 --> BCTmp
	btfss	STATUS,Z
	goto	$+3
	incf	BCDix,f
	return		; les deux nombres sont identiques
	btfss	STATUS,C
	goto	BCD2	; BCTmp<10
	incf	BCDix,f	; BCTmp>10	
	goto	BCD1
BCD2	movlw	D'10'
	addwf	BCTmp,w
	movwf	BCUnit
	return

ConvTLM	swapf	Ttmp1,f		; transforme la temperature normale au format lm92
	rrf	Ttmp1,w
	andlw	B'01111000'
	movwf	Ttmp1	; (Ttmp2:Tmp1)
	rrf	Ttmp2,f
	btfsc	STATUS,C
	bsf	Ttmp1,7
	bcf	Ttmp2,7
	return

ConvLMT	btfsc	Tlue_ent,7		; tranforme la température lue au format LM92 au format normal
	goto	horsplage		; uniquement pour Tlue
	rlf	Tlue_ent,f		; => procédure avec Tlue_ent et Tlue_virg
	bsf	Tlue_ent,0
	btfss	Tlue_virg,7
	bcf	Tlue_ent,0
	rlf	Tlue_virg,f
	swapf	Tlue_virg,w
	andlw	B'00001111'
	movwf	Tlue_virg
	return
horsplage	bsf	hp
	return

Moy_equil	movlw	D'32'		; calcule la moyenne entiere des 128 équilibres précédents
	movwf	nb_prel
	clrf	sum_msb
	bcf	STATUS,IRP
	movlw	0x60
	movwf	FSR
	movf	INDF,w
	movwf	sum_lsb		; on place le 1er equilibre
loop_moy1	decfsz	nb_prel,f
	goto	$+2
	goto	moy2
	incf	FSR,f
	movf	INDF,w
	addwf	sum_lsb,f
	btfsc	STATUS,C
	incf	sum_msb,f	; on incremente msb si lsb>0xFF
	goto	loop_moy1
moy2	movlw	D'96'
	movwf	nb_prel
	movlw	0xA0
	movwf	FSR
	movf	INDF,w
	addwf	sum_lsb,f
	btfsc	STATUS,C
	incf	sum_msb,f	; on incrémente msb si lsb>0xFF
loop_moy2	decfsz	nb_prel,f
	goto	$+2
	goto	new_equil
	incf	FSR,f
	movf	INDF,w
	addwf	sum_lsb,f
	btfss	STATUS,C
	goto	loop_moy2
	incf	sum_msb,f
	goto	loop_moy2
new_equil	bsf	sum_lsb,0
	btfss	sum_lsb,7
	bcf	sum_lsb,0
	movlw	0x01
	andwf	sum_lsb,f	; on récupere le bit 7 et on le met en 0 et on efface tous les autres
	bsf	sum_lsb,1
	btfss	sum_msb,0
	bcf	sum_lsb,1
	bsf	sum_lsb,2
	btfss	sum_msb,1
	bcf	sum_lsb,2
	bsf	sum_lsb,3
	btfss	sum_msb,2
	bcf	sum_lsb,3
	bsf	sum_lsb,4
	btfss	sum_msb,3
	bcf	sum_lsb,4
	bsf	sum_lsb,5
	btfss	sum_msb,4
	bcf	sum_lsb,5
	bsf	sum_lsb,6
	btfss	sum_msb,5
	bcf	sum_lsb,6
	bsf	sum_lsb,7
	btfss	sum_msb,6
	bcf	sum_lsb,7	; l'equilibre trouvé est obligatoirement sur 8 (7) bits donc on peut s'arreter là
	movf	sum_lsb,w
	movwf	equil
	movwf	donnee
	movlw	0x2B
	call	WriteEE		; on enregistre en eeprom le nouvel équilibre
	return

Save_Equil	btfsc	fsr_tmp,7	; à quelle banque doit on aller ?
	goto	ram_bank1
	movf	fsr_tmp,w
	movwf	FSR	; enregistrement
	movf	pwm,w
	movwf	INDF
	incf	fsr_tmp,f
	btfss	fsr_tmp,7	; changement de banque pour la suite ?
	return
	movlw	0xA0
	movwf	fsr_tmp
	return
ram_bank1	movf	fsr_tmp,w	; enregistrement dans la 2nde partie de la RAM
	movwf	FSR
	movf	pwm,w
	movwf	INDF
	incf	fsr_tmp,f
	btfss	STATUS,Z	; terminé ?
	return
new	movlw	0x60	; les 128 elements ont été enregistrés
	movwf	fsr_tmp
	goto	Moy_equil

Toffset	btfss	offset_pos		; Procédure qui ajoute/enlève l'offset à la température 
	goto	negofst
	movf	offset_ent,w
	addwf	Tlue_ent,f
	movf	offset_virg,w
	addwf	Tlue_virg,f
	btfss	Tlue_virg,4		; si ça a dépassé les 4 bits
	return		; ça n'a pas dépassé les 4 bits possibles dont c'est bon
	movlw	B'00010000'
	subwf	Tlue_virg,f	; on enleve la partie entière de Tlue_virg
	incf	Tlue_ent,f	; on incrémente Tlue_ent
	return
negofst	movf	offset_ent,w
	subwf	Tlue_ent,f
	movf	offset_virg,w
	subwf	Tlue_virg,f
	btfsc	STATUS,Z
	return		; c'est bon le resultat est 0 pour la virgule
	btfsc	STATUS,C
	return		; c'est bon le resultat est >0
	decf	Tlue_ent,f	; on décrémente Tlue_ent
	movf	Tlue_virg,w
	subwf	offset_virg,w	; offset_virg - Tlue_virg -> w
	sublw	B'00010000'		; 10000 - w
	movwf	Tlue_virg
	return

Ecart	movf	Tlue_ent,w
	subwf	Tcons_ent,w		; Tcons-Tlue
	btfsc	STATUS,Z
	goto	Egal		; les parties entieres sont égales
	btfss	STATUS,C		; C=1 => Tcons>Tlue
	goto	tluesup		; Tlue>Tcons
	movf	Tlue_ent,w		; Tcons>Tlue
	subwf	Tcons_ent,w
	andlw	B'00001111'
	movwf	diff
	movlw	D'1'
	subwf	diff,f		; on enleve 1
	swapf	diff,f		; les 4 bits de difference en MSb
	movf	Tlue_virg,w
	sublw	B'00010000'		; 10000 - Tlue_virg
	addwf	diff,f
	movf	Tcons_virg,w
	addwf	diff,f	
	bcf	lue_sup
	return
tluesup	movf	Tcons_ent,w		; dans le cas ou Tcons>Tlue
	subwf	Tlue_ent,w
	andlw	B'00001111'
	movwf	diff
	movlw	D'1'
	subwf	diff,f		; on enleve 1
	swapf	diff,f		; les 4 bits de difference en MSb
	movf	Tcons_virg,w
	sublw	B'00010000'		; 10000 - Tlue_virg
	addwf	diff,f
	movf	Tlue_virg,w
	addwf	diff,f
	bsf	lue_sup		; Tlue supérieure
	return
Egal	movf	Tlue_virg,w		; les parties entieres sont égales : on teste l'inegalité puis l'ecart
	subwf	Tcons_virg,w	; Tcons_virg - Tlue_virg
	btfss	STATUS,C
	goto	comp_lc	; Tlue>Tcons
	andlw	B'00001111'
	movwf	diff	; Tcons>Tlue
	bcf	lue_sup
	return
comp_lc	movf	Tcons_virg,w
	subwf	Tlue_virg,w
	andlw	B'00001111'
	movwf	diff
	bsf	lue_sup
	return

Virgule	movwf	DvTmp	; prépare la notation en 4 digits de la virgule, pres à l'affichage
	movwf	DvTmp2
	movf	DvTmp2,w
	addwf	DvTmp,f	; DvTmp x2
	movlw	0x07
	movwf	PCLATH
	movf	DvTmp,w
	call	tableau	; on retrouve la valeur à afficher
	movwf	DvTmp2
	andlw	B'11110000'
	movwf	Dv0
	swapf	Dv0,w
	ASCII
	movwf	Dv0		; Dv0 = plus fort terme (10^-1)
	movlw	B'00001111'
	andwf	DvTmp2,w
	ASCII
	movwf	Dv1
	incf	DvTmp,f
	movlw	0x07
	movwf	PCLATH
	movf	DvTmp,w
	call	tableau
	movwf	DvTmp2
	andlw	B'11110000'
	movwf	Dv2
	swapf	Dv2,w
	ASCII
	movwf	Dv2
	movlw	B'00001111'
	andwf	DvTmp2,w
	ASCII
	movwf	Dv3		; Dv3 = terme plus faible (10^-4)
	return	

; Routines d'affichage de la température
; ======================================

SendCmd	bcf	LCD_RS
	movwf	LCDTmp
	andlw	B'11110000'
	movwf	PORTB
	VALID
	call	T100u
	swapf	LCDTmp,w
	andlw	B'11110000'
	movwf	PORTB
	VALID
	call	T100u
	return
	
SendData	movwf	LCDTmp
	andlw	B'11110000'
	movwf	PORTB
	bsf	LCD_RS
	VALID
	call	T100u
	swapf	LCDTmp,w
	andlw	B'11110000'
	movwf	PORTB
	bsf	LCD_RS
	VALID
	call	T100u
	return

ClrDisp	movlw	0x01	; clear display
	call	SendCmd
	movlw	D'20'
	movwf	var1
Compte	call	T100u	; attends 2ms
	decfsz	var1,f
	goto	Compte
	return

AffOptn	movlw	B'10000100'	; 4eme position LCD
	call	SendCmd
	movlw	0x27	; adresse dans Flash
	movwf	var1
	movlw	D'7'	; longueur de "Option "
	movwf	var3
	call	AffMsg
	movf	var4,w
	ASCII
	call	SendData
	return

AffRegl	movlw	B'11000000'	; 2eme ligne position 1
	call	SendCmd
	movlw	0x7C
	movwf	var1
	movlw	D'7'	; longueur de "Reglage"
	movwf	var3
	call	AffMsg
	movlw	' '
	call	SendData
	return
	
AffMsg	call	ReadFlash	; ecrit un message sur le LCD (adr var2:var1, longueur var3, origine=Flash)
	call	SendData	; affiche le caractere retourné dans w par ReadFlash
	incf	var1,f
	decfsz	var3,f
	goto	AffMsg
	return

Fleche_D	movlw	B'10001111'
	call	SendCmd
	movlw	B'01111110'
	call	SendData
	return

Fleche_G	movlw	B'10000000'
	call	SendCmd
	movlw	B'01111111'
	call	SendData
	return

Aff_ON	movlw	'O'
	call	SendData
	movlw	'N'
	call	SendData
	movlw	' '
	call	SendData
	return	

Aff_OFF	movlw	'O'
	call	SendData
	movlw	'F'
	call	SendData
	movlw	'F'
	call	SendData
	return

Taffich	movf	Taff_ent,w
	call	BCD
	movf	BCDix,w
	ASCII
	call	SendData
	movf	BCUnit,w
	ASCII
	call	SendData
	movlw	B'00101100'
	call	SendData
	movf	Taff_virg,w
	call	Virgule
	movf	Dv0,w
	call	SendData
	movf	Dv1,w
	call	SendData
	movf	Dv2,w
	call	SendData
	movf	Dv3,w
	call	SendData
	movlw	' '
	call	SendData
	movlw	B'11011111'
	call	SendData
	movlw	'C'
	call	SendData
	return

; Routine de Lecture / Ecriture EEPROM/FLASH
; ==========================================

ReadEE	bsf	STATUS,RP1	; lecture donnée EEPROM (adresse dans w, donnée retournée dans W)
	movwf	EEADR
	bsf	STATUS,RP0
	bcf	EECON1,EEPGD
	bsf	EECON1,RD
	bcf	STATUS,RP0
	movf	EEDATA,w
	bcf	STATUS,RP1
	return

WriteEE	bsf	STATUS,RP1	; ecriture donnée EEPROM (adresse dans w, donnée dans "donnee")
	bcf	STATUS,RP0	; bank2
	movwf	EEADR
	bcf	STATUS,RP1	; direct adressing => changement de banque !
	movf	donnee,w
	bsf	STATUS,RP1
	movwf	EEDATA
	bsf	STATUS,RP0	; bank3
	bcf	EECON1,EEPGD
	bsf	EECON1,WREN
	bcf	INTCON,GIE
	movlw	H'55'
	movwf	EECON2
	movlw	H'AA'
	movwf	EECON2
	bsf	EECON1,WR
	BANK0
	btfss	PIR2,EEIF
	goto	$-1
	bcf	PIR2,EEIF
	bsf	STATUS,RP0	; bank3
	bsf	STATUS,RP1
	bcf	EECON1,WREN
	BANK0
	return

ReadFlash	movf	var1,w
	bsf	STATUS,RP1		; lecture FLASH (adr. 0xvar2:var1, donnée dans w)
	bcf	STATUS,RP0	; bank2
	movwf	EEADR	; LSb adr.
	movlw	0x0C	
	movwf	EEADRH	; MSb adr.
	bsf	STATUS,RP0	; bank3
	bsf	EECON1,EEPGD
	bsf	EECON1,RD
	nop
	nop
	bcf	STATUS,RP0	; bank2
	movf	EEDATA,w
	bcf	STATUS,RP1
	return

	org	H'07C0'	; tableau de valeurs s'etendant jusqu'à 07FD (pas de debordement)
tableau	addwf	PCL,f	; décalage adresse mémoire
	retlw	0x00	; début des parametres affichages (+0)
	retlw	0x00
	retlw	0x06
	retlw	0x25
	retlw	0x12
	retlw	0x50
	retlw	0x18
	retlw	0x75
	retlw	0x25
	retlw	0x00
	retlw	0x31
	retlw	0x25
	retlw	0x37
	retlw	0x50
	retlw	0x43
	retlw	0x75
	retlw	0x50
	retlw	0x00
	retlw	0x56
	retlw	0x25
	retlw	0x62
	retlw	0x50
	retlw	0x68
	retlw	0x75
	retlw	0x75
	retlw	0x00
	retlw	0x81
	retlw	0x25
	retlw	0x87
	retlw	0x50
	retlw	0x93
	retlw	0x75	; fin des parametres affichage
	retlw	D'15'	; début paramatres equation equilibre (+ D'32')  
	retlw	D'15'	; +0.0625, 0.125
	retlw	D'25'	; +0.1875
	retlw	D'50'	; +0.25, 0.3125
	retlw	D'50'	;
	retlw	D'3'	; -0.0625, 0.125 (début négatif : + D'37')
	retlw	D'3'	;
	retlw	D'7'	; -1.875
	retlw	D'10'	; -2.5, 0.3125
	retlw	D'10'	;
	retlw	D'20'	; -0.375, 0.4275
	retlw	D'20'	;
	retlw	D'30'	; -0.5

; Données initiales en EEPROM
; ===========================

	org	H'2120'
	de	0x25, 0x08, 0x23, 0x00, 0x27, 0x00, 0x00, 0x00	; parametres Menu
	de	0x05, 0x3C, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00	; paramètres Menu
					; à adresser à partir de 0x20

; Messages LCD enregistrés en FLASH (page 1)
; ==========================================

	org	H'0C00'	; adresse début page 1
	de	'T', 'e', 'm', 'p', 'e', 'r', 'a', 't'
	de	'u', 'r', 'e', 'C', 'o', 'u', 'v', 'e'
	de	'u', 's', 'e', 'G', 'e', 's', 't', 'i'
	de	'o', 'n', ' ', 'T', 0xDF, 'H', 'o', 'r'
	de	's', ' ', 'P', 'l', 'a', 'g', 'e', 'O'
	de	'p', 't', 'i', 'o', 'n', ' ', 'T', 0xDF
	de	' ', 'C', 'o', 'n', 's', 'i', 'g', 'n'
	de	'e', ' ', 0x28, 0xDF, 'C', 0x29, 'T', 'o'
	de	'n', ' ', 0x28, 's', 'e', 'c', 0x2E, 0x29
	de	'T', 'o', 'f', 'f', ' ', 0x28, 'm', 'i'
	de	'n', 0x2E, 0x29, 'T', 0xDF, 'm', 'i', 'n'
	de	' ', 0x28, 0xDF, 'C', 0x29, 'T', 0xDF, 'm'
	de	'a', 'x', ' ', 0x28, 0xDF, 'C', 0x29, 'O'
	de	'f', 'f', 's', 'e', 't', ' ', 0x28, 0xDF
	de	'C', 0x29, 'E', 'n', 'r', 'e', 'g', 'i'
	de	's', 't', 'r', 'e', 'R', 'e', 'g', 'l'
	de	'a', 'g', 'e', 'M', 'a', 'r', 'c', 'h'
	de	'e', 0x2F, 'A', 'r', 'r', 'e', 't', 'T'
	de	0xDF, 'c', 'o', 'n', 's', 'E', 't', 'a'
	de	'l', 'o', 'n', 'n', 'a', 'g', 'e', 'T'
	de	'e', 'm', 'p', 'o', 's', ' ', 0x3A, ' '
	de	'C', 'a', 'p', 't', 'e', 'u', 'r', ' '
	de	'n', 'o', 'n', 'c', 'o', 'n', 'n', 'e'
	de	'c', 't', 'e'

; "Temperature" = adr 0C00, lg=11
; "Couveuse" = 0C0B, lg=8
; "Gestion T°" = 0C13, lg=10
; "Hors Plage" = 0C1D, lg=10
; "Option " = 0C27, lg=7
; "T° Consigne (°C)" = 0C2E, lg=16
; "Ton (sec.)" = 0C3E, lg=10
; "Toff (min.)" = 0C48, lg=11
; "T°min (°C)" = 0C53, lg=10
; "T°max (°C)" = 0C5D, lg=10
; "Offset (°C)" = 0C67, lg=11
; "Enregistre" = 0C72, lg=10
; "Reglage" = 0C7C, lg=7
; "Marche/Arret" = 0C83, lg=12
; "T°cons" = 0C8F, lg=6
; "Etalonnage" = 0C95, lg=10
; "Tempos" = 0C9F, lg=6
; " : " = 0CA5, lg=3
; "Capteur non", =0CA8, lg=11
; "connecté", =0CB3, lg=8

	END
