;choisir Tab Size = 10 dans les options de l'éditeur de MPLAB IDE
;pour obtenir un alignement correct du listing
;
;si vous visualisez avec Wordpad, vous aurez des soucis d'alignement...
;choisissez dans les options de Wordpad "pas de retour à la ligne"
;sinon les longues lignes de commentaires seront tronquées
;et passeront dans les colonnes étiquettes et code
;**********************************************************************
;

;
;
;LISTE DES PRINCIPALES PROCEDURES: (Double-clic sur 1 mot puis F3 dans MPLAB, c'est pratique...)
;TESTS
;MACROS
;mot16A	macro ;charge AH et AL avec le mot codé sur 16 bits transmis
;mot16B	macro ;charge BH et BL avec le mot codé sur 16 bits transmis
;Changements de banques
;R_EEPROM
;W_EEPROM
;CONSTANTES
;VARIABLES_EN_BANQUE0

;INITIALISATION DES PORTS
;PROGRAMMATION DU REGISTRE OPTION (BANK1)
;PROG DU REGISTRE INTCON (BANK0)
;PROG DU REGISTRE T1CON (BANK0)
;PROG DU REGISTRE T2CON (BANK0)
;PROG DU REGISTRE PR2 (BANK1)
;PROG DU REGISTRE PIE1 (BANK1)

;Initialisation_des_variables

;BOUCLE_PRINCIPALE

;inttimer0 -> le Timer0 est utilisé au sein de l'INT portB0 (voir plus bas) pour mesurer la durée PPM voie GAZ
;inttimer1 -> le Timer1 est utilisé dans l'INT portB4-7 (voir plus bas) pour mesurer la durée PPM voie ANTI-COUPLE
;inttimer2 -> generation du signal de sortie
;intB0
;intB5


;convhbin	;conversion sexadécimale -> binaire ;entrée: AA, BB ;resultat: AH,AL = 60*AA+BB
;multi	;mutiplication 8 bits x 8 bits de AA par w (données sur 1 octet) ;resultat (sur 2 octets) dans AH,AL
;divi2	;division d'une valeur codée sur 16 bits (AH,AL) par 2
;divi60	;division d'une valeur codée sur 16 bits (AH,AL) par 60 ;résultat dans w ;reste de la division dans (BH,BL)
;add16A	;addition 16bits résultat dans A ;(AH,AL)+(BH,BL) -> (AH,AL)
;add16B	;addition 16bits résultat dans B ;(AH,AL)+(BH,BL) -> (BH,BL)
;cpl16x	;complément à deux de la variable codée sur 2 octets situés aux adresses w et w+1 permet les soustractions
;compa16p	;comparaison de deux valeurs codées sur 16 bits (AH,AL à BH,BL) ;resultat dans STATUS carry et zéro 
;movxA	;mov la variable codée sur 2 octets situés aux adresses w et w+1  dans -> AH,AL
;movAx	;mov AH,AL dans -> la variable codée sur 2 octets situés aux adresses w et w+1  
;movxB	;mov la variable codée sur 2 octets situés aux adresses w et w+1  dans -> BH,BL
;movBx	;mov BH,BL dans -> la variable codée sur 2 octets situés aux adresses w et w+1 

;procédures d'affichage LCD

;cvBDU	;CONVERSION BINAIRE(1) (1 octet incomplet 0..99 et pas 0..255) --> BCD ;nombre à convertir dans AA
;cvBCU	;CONVERSION BINAIRE(2) (1 octet complet 0..255) --> BCD ;resultat dans BB (centaines) et dans AA (unités)

;tp154us
;tp1ms
;tp2ms
;tp10ms
;tp100ms

;vari_vit

;TABLEAUX
;
;
;			;pour Qx=20,000 Mhz
;
;
;
;

;***********************************************************************************************
;	VARIATEUR pour moteur DC (pour hélico Piccolo)  : variat2_05.asm
;		pour PIC16F628
;		par Silicium 628
;************************************************************************************************
;dernière mise à jour: 29/05/2005
;remarque: suite aux modifications (=améliorations!) certains commentaires peuvent se révéler faux !!!
;j'en suis désolé. Je relis régulièrement les commentaires et essaye de les tenir à jour.
;toutefois il m'arrive de trouver des énormités ! que je corrige...
;------------------------------------------------------------------------------------------------




;*********************************************** PRINCIPE *****************************************
;int Extérieure par bit 0 du port B sert à detecter les fronts du signal PPM du récepteur de radio-commande
;on en déduit sa durée (1 à 2,2 ms)



;******************************** REMARQUES GENERALES *********************************************

;représentation d'un nombre hexadécimal: commence par "0x" ex:  0x20
;représentation d'un nombre décimal: commence par "." ex:  .20
; ex: 0x20 = .32
; B'00010000' represente une valeur binaire
;Utiliser une version récente de MPLAB afin que le PIC16F628 soit pris en compte (ma version= 5.70.00 )
;voir sur le site de Microchip(R): http://www.microchip.com

;***************************************************************************************************

;----------------------------------------------------------------------

	list      p=16f628            ; list directive to define processor
	#include <p16f628.inc>        ; processor specific variable definitions


	__CONFIG   _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _MCLRE_ON & _LVP_OFF


; '__CONFIG' précise les paramètres encodés dans le processeur au moment de
; la programmation du processeur. Les définitions sont dans le fichier include.
; Voici les valeurs et leurs définitions :
;	_CP_ON		Code protection ON : impossible de relire
;	_CP_OFF		Code protection OFF

;	_PWRTE_ON		Timer reset sur power on en service
;	_PWRTE_OFF	Timer reset hors-service

;	_WDT_ON		Watch-dog en service
;	_WDT_OFF		Watch-dog hors service

;	_LP_OSC		Oscillateur quartz basse vitesse   (32<F<200Khz)
;	_XT_OSC		Oscillateur quartz moyenne vitesse (200Khz<F<4Mhz)
;	_HS_OSC		Oscillateur quartz grande vitesse  (4Mhz<F<20Mhz)
;	_RC_OSC		Oscillateur à réseau RC

; Reset du PIC si tension <4V
; ------------------------------
; 	_BODEN_ON	Reset tension en service Valide PWRTE_ON automatiquement
; 	_BODEN_OFF	Reset tension hors service

; Programmation sur circuit
; -------------------------
;	_LVP_ON		RB4 permet la programmation série du PIC
;	_LVP_OFF		RB4 en utilisation normale


;           
;	"departRam equ 0x20"
;----------------------------------------------------------------------

;*****************************************************************************
;                             MACROS                                         *
;*****************************************************************************

mot16A	macro	mot16	;charge AH et AL avec le mot codé sur 16 bits transmis
	movlw	low mot16
	movwf	AL
	movlw	high mot16
	movwf	AH
	endm

mot16B	macro	mot16	;charge BH et BL avec le mot codé sur 16 bits transmis
	movlw	low mot16
	movwf	BL
	movlw	high mot16
	movwf	BH
	endm	


; Changements de banques

BANK0	macro			; passer en banque0
	bcf	STATUS,RP0
	bcf	STATUS,RP1
	endm

BANK1	macro			; passer en banque1
	bsf	STATUS,RP0
	bcf	STATUS,RP1
	endm

BANK2	macro			; passer en banque2
	bcf	STATUS,RP0
	bsf	STATUS,RP1
	endm

BANK3	macro			; passer en banque3
	bsf	STATUS,RP0
	bsf	STATUS,RP1
	endm

; lire eeprom (adresse et résultat en w) 
R_EEPROM 	macro 			
	clrwdt
	bsf 	STATUS,RP0 	; Bank 1
	movwf 	EEADR		; Adresse to read
	bsf 	EECON1,RD 	; ordre de lecture
	movf 	EEDATA,w 		; W = EEDATA
	bcf 	STATUS,RP0 	; Bank 0
	endm

;ecriture en EEPROM (adresse dans DDD (commun 4 banques), data dans w)
W_EEPROM	macro
	clrwdt	
	LOCAL	loop
	bsf 	STATUS,RP0	; Bank 1
	movwf 	EEDATA 		; Data to write
;	movlw	adress1		; adresse passée en paramètre à la macro (moins souple que par registre)
	movf	DDD,w		; adresse passée par registre DDD, commun aux 4 banques
	movwf 	EEADR
	bsf 	EECON1, WREN	; Enable Write
	bcf 	INTCON, GIE 	; Disable INTs
	movlw 	0x55
	movwf 	EECON2 		; Write 55
	movlw 	0xAA
	movwf 	EECON2 		; Write AA
	bsf 	EECON1, WR 	; lancer cycle d'écriture
	bsf 	INTCON, GIE	; réautoriser INTs

loop 	clrwdt
	btfsc EECON1 , WR 		; tester si écriture terminée
	goto loop 		; non, attendre 
	bcf EECON1 , WREN 		; verrouiller prochaine écriture 
	bcf STATUS , RP0 		; passer en banque0
	endm

;*****************************************************************************
;CONSTANTES

w       	equ	0
f	equ	1

RESET_V	equ	0x0000	; adresse du vecteur de reset
ISR_V	equ	0x0004	; adresse du vecteur d'interruption général



;----------------------------------------------------------------------

;VARIABLES_EN_BANQUE0
;le PIC16F628 possède 224 octets de RAM répartis en 3 emplacements (96+80+48 octets)
;ici première banque de 96 octets, début à l'adresse 0x20
;vérifier sur le listing absolu que la dernière adresse soit < 7Fh
;L'utilisation de CBLOCK permet de permutter facilement les variables (par rapport à "equ" )

	CBLOCK	0x20	;debut de la zone RAM utilisateur de 96 octets en banque 0
	AA	: 1	;registre de travail
	BB	: 1	;registre de travail	
	CC	: 1	;registre de travail
	DD	: 1	;registre de travail

	AH	: 1	;registre de travail poids fort
	AL	: 1	;registre de travail poids faible
	BH	: 1	;registre de travail poids fort
	BL	: 1	;registre de travail poids faible

	count0	: 1	;
	count1	: 1	;utilisé dans la multiplication 8bits x 8bits
	count2	: 1	;utilisé dans la procedure vari_vit

	dtlcd	: 1	;data vers afficheur LCD

	aff1	: 1
	aff2	: 1
	aff3	: 1
	aff4	: 1

	bitn	: 1

	t1	: 1	;pour les tempos
	t2	: 1	;pour les tempos
	t3	: 1	;pour les tempos

	rapcyc1	: 1	;pour faire varier le rapport cyclique du signal de sortie voie ANTI-COUPLE
	rapcyc2	: 1	;pour faire varier le rapport cyclique du signal de sortie voie GAZ
	butcyc2	: 1

	T_PPM_G	: 1	;temps (durée) du signal PPM (voie des GAZ en sortie du récepteur de radiocommande)
	T_PPM_A	: 1	;temps (durée) du signal PPM (voie des ANTI-COUPLE en sortie du récepteur de radiocommande)

	memo1	: 1	;variable locale
	memo2	: 1	;variable locale

	adrEE	: 1	;pour mémoriser en EEPROM


;voir fonctionnement des timer pour l'explication du 255-...

	mesflags	: 1	;8 flags perso divers
;b0: stop moteur principal (GAZ) par ordre émis par la radio-commande (trim des gaz en bas...)
;b1: phase du signal de sortie voie ANTI-COUPLE 	(Timer1)
;b2: phase du signal de sortie voie GAZ 	(Timer2)
;b3:
;b4: mémorise si front montant/descendant en cours sur l'entrée RB0
;b5:
;b6:
;b7: 

	ENDC		; Fin de la zone


;----------------------------------------------------------------------
; VARIABLES ZONE COMMUNE
; Zone de 16 bytes
	CBLOCK 	0x70  	;Début de la zone (0x70 à 0x7F) 
	WW	: 1	;pour sauvegarder w pendant INT
	STUS_TMP	: 1	;pour sauvegarder STATUS pendant INT
	FSR_temp 	: 1 	;sauvegarde FSR (si indirect en interrupt)
	PLATH_tmp : 1 

	DDD	: 1	;registre d'adresses commun

	ENDC		; Fin de la zone

;----------------------------------------------------------------------
;VARIABLES EN BANQUE1 accessible avec IRP=0 si adressage indirect
	CBLOCK 	0xA0 	;=.160 début de la zone RAM utilisateur de 80 octets en banque 1 

	ENDC 		;Fin de la zone
;----------------------------------------------------------------------

	ORG	RESET_V	; Vecteur de RESET
RESET	goto	start


;***********************************************************************
; TRAITEMENT DES INTERRUPTIONS (Aiguillage vers routines)
;***********************************************************************

;ici INT par le Timer 0
;RAPPEL Un seul vecteur d'interruption, d'adresse 004 est diponible
;Quelle que soit la cause de l'interruption, le PC est donc chargé par 004
;à vous ensuite de tester les différents indicateurs pour savoir quel est la source de l'INT.
;voir le registre INTCON

	ORG	ISR_V		; Vecteur d'Interruption
	
	movwf	WW
	swapf	STATUS,w
	movwf	STUS_TMP
	movf 	FSR , w
	movwf 	FSR_temp
	movf 	PCLATH , w 	;charger PCLATH 
	movwf 	PLATH_tmp 	;le sauver 
	clrf 	PCLATH 		;on est en page 0 
	BANK0 			;passer en banque0

intRB0	btfss	INTCON,1		;test FLAG INT extérieure bit 0 du port B
	goto 	intRB5		;non suite
	call	intB0		;oui, traiter interrupt PORTB,0
	bcf	INTCON,1		;effacer flag interupt portB: réautorise interruption PORTB,0
	goto	restorREG

intRB5	btfss	INTCON,0		;test FLAG INT extérieure bits 4 à 7 du port B
	goto 	intTMR1		;non suite
	call	intB5		;oui, traiter interrupt PORTB,0
	bcf	INTCON,0		;effacer flag interupt portB: réautorise interruption PORTB,0
	goto	restorREG


intTMR1	btfss	PIR1,TMR1IF	;test FLAG timer1
	goto 	intTMR0		;non test suivant
	call 	inttimer1		;oui, traiter interrupt timer1
	bcf	PIR1,TMR1IF	;réautorise l'INT par Timer1
	goto	restorREG

intTMR0	btfss	INTCON,2		;test FLAG timer0
	goto 	intTMR2		;non suite
	call	inttimer0		;oui, traiter interrupt timer0
	bcf	INTCON,2		;effacer flag interupt timer: réautorise l'INT Timer0
	goto	restorREG

intTMR2	btfss	PIR1,TMR2IF	;test FLAG timer2
	goto 	restorREG		;non suite... 
	call 	inttimer2		;oui, traiter interrupt timer2
	bcf	PIR1,TMR2IF	;réautorise l'INT par Timer2
	goto	restorREG


restorREG	movf 	PLATH_tmp, w 		;recharger ancien PCLATH 
	movwf	PCLATH
	movf 	FSR_temp,w
	movwf	FSR
	swapf	STUS_TMP,w	;swap STATUS_TMP, résultat dans w
	movwf	STATUS		;restaurer status
	swapf	WW,f		;Inversion L et H de l'ancien W sans modifier Z
	swapf	WW,w		;Ré-inversion de L et H dans W

	retfie			;remet GIE à 1 puis return
	

;***********************************************************************
; START START START START START START START START START START START
;***********************************************************************

	org     ISR_V+.60

start	clrwdt
	bcf	STATUS,IRP	;pour l'adressage indirect
;IRP: Register Bank Select bit (used for indirect addressing)
;=0 -> Bank 0, 1 (00h - FFh)
;=1 -> Bank 2, 3 (100h - 1FFh)

	BANK0			;pour l'adressage direct

;***********************************************************************
;ZONE de TESTS de procédures

;	mot16B	.61000
;	movlw	.335
;	call	divi16_8
;	nop

;	movlw	.200
;	movwf	rapcyc2	;G

;la	movlw	.255
;	movwf	BB	;mancheAC
;	call	calc_AC
	
;	movlw	.10
;	addwf	rapcyc2,f
;	goto	la






;***********************************************************************

	call 	tp100ms

	clrwdt


;***********************************************************************
; INITIALISATION DES PORTS
;***********************************************************************

;RA0=entrée: signal du capteur magnétique (détection de la phase du rotor)
;RA1=entrée: signal en provenance du circuit de détection de vitesse faible ou nulle suite à décrochage du moteur
;RA2=entrée: détection tension alim faible ( "BEC" )
;RA3=sortie: LED alim faible
;RA3=

;RB0=entrée: signal PPM du récepteur de radio-commande, voie 'gaz'
;RB1=
;RB2=sortie: commande MOSFET canal N 
;RB3=
;RB4=
;RB5=s
;RB6=s
;RB7=

	BANK0
	movlw	0x07
	movwf	CMCON		; PORT A en E/S numériques (BANK0)

	BANK1
	movlw	B'00000000'	;0=sortie 1=entree attention RA4 =drain ouvert
	movwf	TRISA		;config du port A (TRISA en page 1)
	movlw	B'00101001'
	movwf	TRISB		;config du port B

	bcf	OPTION_REG,7	;Enable PORTB pull-ups

;----------------------------------------------------------------------
;PROGRAMMATION DU REGISTRE OPTION (BANK1)  -  voir datasheet p:20 du datasheet PIC16F62X.pdf

;bit7:  RBPU =0 -> R tirage à Vdd du port B
;bit6: INTEDG=1 -> INT sur front montant ou descendant de RB0
;		1 = Interrupt on rising edge of RB0/INT pin
;		0 = Interrupt on falling edge of RB0/INT pin

;bit5:  T0CS = 0 -> TMR0 Clock Source Select bit 
;		1 = Transition on RA4/T0CKI pin (Fonctionnement en mode compteur)
;		0 = Internal instruction cycle clock (CLKOUT) (Fonctionnement en mode timer)

;bit4:  RTE = 0 -> inc sur front montant

;bti3:  PSA = 0 -> prédiv affecté au timer0
;bits2,1,0:PS2,1,0   	
;Bit Value TMR0 Rate WDT Rate
;000	1 : 2	1 : 1
;001	1 : 4	1 : 2
;010	1 : 8	1 : 4
;011	1 : 16	1 : 8
;100	1 : 32	1 : 16
;101	1 : 64	1 : 32	***** ICI  100b -> Timer0 = 1/64  *****
;110	1 : 128	1 : 64
;111	1 : 256	1 : 128

	BANK1
;	 nº bits:  '76543210'
	movlw	B'01000101'
	movwf 	OPTION_REG


;----------------------------------------------------------------------
;PROG DU REGISTRE INTCON (BANK0)  -  voir datasheet p:21
;bit7 GIE =0 -> INT GLOBALE interdite. (voir + bas)
;bit6 PEIE=1 -> INT PERIPHERIQUES autorisées. (timer1 en fait partie)
;bit5 T0IE=0 -> INT par debordement Timer0  autorisée.
;bit4 INTE=0 -> INT de RB0/INT autorisées (INTERRUPTIONS EXTERNES)
;bit3 RBIE=1 -> INT du port RB4 à RB7 autorisées.
;bit2 T0IF=x (flag mis à 1 par débordement du Timer0)
;bit1 INTF=x (flag  mis à 1 par une INT provoquée par la libne RB0/INT du port B)
;bit0 RBIF=x (flag mis à 1 si changement d'état des entrées RB4 à RB7 du port B. attention RB1 à RB3 -> pas d'INT)

	BANK0
;	 nº bits:  '76543210'
	movlw	B'01111000'
	movwf	INTCON


;----------------------------------------------------------------------
;PROG DU REGISTRE T1CON (BANK0)
;bit7 :	Inutilisé : lu comme « 0 »
;bit6 :	Inutilisé : lu comme « 0 »
;bit5 :	T1CKPS1 : Timer 1 oscillator ClocK Prescale Select bit 1
;bit4 ;	T1CKPS0 : Timer 1 oscillator ClocK Prescale Select bit 0
;bit3 :	T1OSCEN : Timer 1 OSCillator ENable control bit (oscillateur interne)
;bit2 :	T1SYNC : Timer 1 external clock input SYNChronisation control bit
;bit1 :	TMR1CS : TiMeR 1 Clock Source select bit  (0=internal clock)
;bit0 :	TMR1ON : TiMeR 1 ON bit

	BANK0
;	 nº bits:  '76543210'
	movlw	B'00110001'	;prescale Timer1=1/8
	movwf	T1CON

;----------------------------------------------------------------------

;PROG DU REGISTRE T2CON (BANK0)

;bit 7: Unimplemented: Read as '0'
;bit 6-3: TOUTPS3:TOUTPS0: Timer2 Output Postscale Select bits
;0000 = 1:1 Postscale 
;0001 = 1:2 Postscale
;0010 = 1:3 Postscale
;0011 = 1:4 Postscale  
;0100 = 1:5 Postscale etc... (valeur binaire +1)
;1111 = 1:16 Postscale 

;bit 2: TMR2ON: Timer2 On bit =1 : Timer2 is on
;bit 1-0: T2CKPS1:T2CKPS0: Timer2 Clock Prescale Select bits
;00 = Prescaler = 1	
;01 = Prescaler = 4 
;1x = Prescaler = 16 (valeur choisie ici)

	BANK0
;	 nº bits:  '76543210'
	movlw	B'00000110'
	movwf	T2CON

;----------------------------------------------------------------------
;PROG DU REGISTRE PR2 (BANK1)
;utilisé par timer2
	BANK1
	movlw	.64
	movwf	PR2

;----------------------------------------------------------------------
;PROG DU REGISTRE PIE1 (BANK1)
;bit7 : PSPIE b7 : Toujours 0 sur PIC 16F876
;bit6 : ADIE  : masque int convertisseur A/D 
;bit5 : RCIE  : masque int réception USART 
;bit4 : TXIE  : masque int transmission USART 
;bit3 : SSPIE : masque int port série synchrone 
;bit2 : CCP1IE: masque int CCP1 
;bit1 : TMR2IE: masque int TMR2 = PR2 
;bit0 : TMR1IE: masque int débordement tmr1

	BANK1
;	 nº bits:  '76543210'
	movlw	B'00000011'	;enable INT TIMER1 - enable INT TIMER2 - disable int réception USART (port série)
	movwf	PIE1


;----------------------------------------------------------------------

;Initialisation_des_variables

initvar	clrwdt
	BANK0

	movlw	B'00000001'	;STOP moteur !
	movwf	mesflags

	clrf	count2
	clrf	DDD

  	movlw	.200	
	movwf	TMR0

	clrf	TMR1L
	clrf	TMR1H

  	movlw	.128	
	movwf	TMR2
  	
	movlw	.5
	movwf	T_PPM_G
	movlw	.128
	movwf	T_PPM_A

	movlw	.1
	movwf	rapcyc1
	movwf	rapcyc2
	
	bsf 	INTCON, GIE	;->INT GLOBALE autorisée


;-----------------------------------------------------------------------
;	clrwdt

;RAZ LCD
;	call 	dspclr
;	call 	home
;	call 	fset
;	call 	setmod0
;	call 	dsp10

;	movlw	"V"
;	call	ecrire
;	movlw	"a"
;	call	ecrire
;	movlw	"r"
;	call	ecrire
;	movlw	"i"
;	call	ecrire
;	movlw	"a"
;	call	ecrire
;	movlw	"t"
;	call	ecrire
;	call	tp100ms


;------------------------------------------------------------------------------------------------------------------
;BOUCLE_PRINCIPALE

boucle1	BANK0

	call	tp10ms	;DETERMINE LA VITESSE DE REPONSE

;	btfss	PORTB,3
;	call	ecrireEE	;pour test uniquement

;CES AFFICHAGES SONT DESTINES A UN AFFICHEUR LCD INTERFACE SUR LE PORT A
;pour la phase de mise au point uniquement. (Ralentit la réponse globale)
	
;	movlw	00h	;affiche en ligne1 du LCD
;	call	ddras
;	movf	rapcyc2,w
;	call	affiw
;	movlw	40h	;affiche en ligne2 du LCD
;	call	ddras
;	comf	rapcyc1,w
;	call	affiw

;------------------------------------------------------------------------------------------------------------------
;ajustement du rapport cyclique en fonction du signal ' VOIE GAZ'
;T_PPM est calculé dans la procédure durée du signal PPM VOIE GAZ
;(T_PPM = 84..173 avec un Qx=20MHz) 


;arret moteur en dessous d'une valeur palier

	movlw	.88		;valeur de T_PPM au dessous de laquelle on va stopper le moteur
	subwf	T_PPM_G,w		;w:= T_PPM - 88 (result -> w : ne touche pas à T_PPM)
	btfsc	STATUS,0		;c=0 ?    (c=0 si  f < 5 )
	goto	test2
	bsf	mesflags,0	;oui: ARRET D'URGENCE (si manche + trim gaz au mini)
	goto	tppm1

test2	movlw	.5		;valeur de rapcyc2 au dessous de laquelle on va stopper le moteur
	subwf	rapcyc2,w		;w:= rapcyc2 - 5 (result -> w : ne touche pas à rapcyc2)
	btfss	STATUS,0		;c=0 ?    (c=0 si  f < 5 )
	goto	stop		;oui
	goto	go		;non
	
stop	bsf	mesflags,0	;oui: STOP
;	clrf	butcyc2
; 	clrf	rapcyc2		
	goto	tppm1
	
go	btfsc	STATUS,0		;même question
	bcf	mesflags,0	;non: pas STOP

;calcul du rapport cyclique
tppm1	movf	T_PPM_G,w
	movwf	memo1
	movlw	.84		; T_PPM_G mini CETTE VALEUR EST A AJUSTER EN FONCTION DE VOTRE RADIO
	subwf	memo1,f		; T_PPM_G:= T_PPM_G - 84 (pré-ofset)
	btfss	STATUS,0		;débordement ?
	clrf	memo1		;oui
	rlf	memo1,w		; w:= 2 x T_PPM_G
	addwf	memo1,w		; w:= 3 x T_PPM_G
	btfsc	STATUS,0		;débordement ? (résult > 255 ?)
	movlw	.253		;oui, butée haute
	movwf	butcyc2

;calibrage final
	movlw	.253		;valeur max de rapcycl admissible (attention: si > 253 -> int Timer2 = HS)
				;avec prediv =1/16 (voir T2CON)
	subwf	butcyc2,w		;w:= rapcycl - 240 (result -> w : ne touche pas à rapcycl) d=f-w
	btfss	STATUS,0		;c=0 ?  rapcycl < 240 ?   (c=0 si  w > f )
	goto	fincal		;oui
	movlw	.253		;non alors on bloque à butée max 
	movwf	butcyc2

fincal	nop
;progressivité de la réponse (pour éviter de casser les dents de la roue dentée en plastique sur l'arbre rotor)
;on fait tendre progressivement rapcyc2 vers butcycl2
;-------------------------------
rapvari	movf	rapcyc2,w
	subwf	butcyc2,w
	btfsc	STATUS,2		;z
	goto	finrapv
	btfss	STATUS,0		;c
	goto	moins
	goto	plus
	
moins	decf	rapcyc2,f
;	movlw	.2
;	call	tx10ms		;décroissance lente
	goto	finrapv	
	
plus	incf	rapcyc2,f

finrapv	nop

	
;------------------------------------------------------------------------------------------------------------------
;ajustement du rapport cyclique en fonction du signal ' voie ANTI-COUPLE'
;T_PPM est calculé dans la procédure durée du signal PPM voie ANTI-COUPLE
;=========================================
;RAPPEL:
;les valeurs du rapport cycliques sont codées sur un octet
;le rapport cyclique varie entre 0% et 100% c.a.d. en analogique [0..1] ce qu'on code ici sur un octet [0..255]
;il y a donc 256 pas possibles 

;VOICI LE MIXAGE UTILISE:
;AC=(G*G/256 * Manche_AC /170 + G)/2	qui s'annule pour GAZ=0 mais pas pour AC=0
;ou son équivalent qui évite 1 débordement:
;AC=G*G/256/2*Manche_AC/170 + G/2
;cette courbe du second degré (gaz " au carré") a été déterminé empiriquement
;Les calculs se font sur deux octets mais les résultats sont réencodés sur un octet
;=========================================

;calcul du signal voie ANTI-COUPLE
tppm2	movf	T_PPM_A,w	;manche anti-couple
	movwf	memo1
	movlw	.84	; T_PPM_A mini CETTE VALEUR EST A AJUSTER EN FONCTION DE VOTRE RADIO
	subwf	memo1,f	; T_PPM_A:= T_PPM_A - 84 (pré-ofset)
	btfss	STATUS,0	;débordement ?
	clrf	memo1	;oui
	rlf	memo1,w	; w:= 2 x T_PPM_A
	addwf	memo1,w	; w:= 3 x T_PPM_A
	btfsc	STATUS,0	;débordement ? (résult > 255 ?)
	movlw	.250	;oui, butée haute
	movwf	BB	;non, on garde le résultat obtenu	BB=AntiCouple
	
;calcul du rapport cyclique (mixage de la valeur obtenue avec celle de la voie "GAZ")
calc_AC	movf	rapcyc2,w	;w=GAZ
	movwf	AA
	call	multi	;w*AA ->  AH,L = GAZ*GAZ =GAZ^2	;	AL=GAZ^2/256
	movf	BB,w	;w=manche AntiCouple
	movwf	AA	;AA=manche AntiCouple
	bcf	STATUS,0	;RAZ c
	rrf	AH,w	;w=G*G/256/2
	call	multi	;w*AA ->  AH,L = G*G/256/2 * Manche_AC
	movlw	AH	;w=adresse du registre AA
	call	movxB	;BH,L = AH,L donc BH,L := G*G/256/2 * Manche_AC
	movlw	.170	;dividende
	call	divi16_8	; w:=BH,L / 170 =  G*G/256/2 * Manche_AC / 170
	movwf	AA	;AA:=BH,L / 170 =  G*G/256/2 * Manche_AC / 170
	bcf	STATUS,0	;RAZ c
	rrf	rapcyc2,w	;w:=G/2
	addwf	AA,f	;AA:=G*G/256/2 * Manche_AC / 170 +G/2
	btfss	STATUS,0	;c dépassement ?
	goto	clc2	;non
	movlw	0xFF	;oui, on force à 255
	movwf	AA
	
clc2	comf	AA,w	;pour agir dans le bon sens (les 2 moteurs doivent accélérer en même temps)
	movwf	rapcyc1	;rapcyc1=resultat
	
;	comf	rapcyc1,f	;POUR TEST SEULEMENT
;	return		;POUR TEST SEULEMENT

;calibrage final
	movlw	.250	;valeur max de rapcycl admissible (attention: si > 250 -> int Timer2 = HS)
			;avec prediv =1/8 (voir T1CON)
	subwf	rapcyc1,w	;w:= rapcycl - 240 (result -> w : ne touche pas à rapcycl) d=f-w
	btfss	STATUS,0	;c=0 ?  rapcycl < 240 ?   (c=0 si  w > f )
	goto	finbcl1	;oui
	movlw	.250	;non alors on bloque à butée max 
	movwf	rapcyc1
	

;------------------------------------------------------------------------------------------------------------------

finbcl1  	goto	boucle1

;-----------------------------------------------------------------------
;DEBUT DES PROCEDURES
;-----------------------------------------------------------------------

;***********************************************************************
; SOUS-ROUTINES d'INTERRUPTIONS
;***********************************************************************
;int timer0
;en principe ne déborde jamais ici. 
;est utilisé au sein de l'INT portB0 (voir plus bas) pour mesurer la durée PPM voie GAZ

inttimer0	

fintimer0	return	

;----------------------------------------------------------------------
;int timer1
;génération du signal de sortie voie ANTI-COUPLE
;ce timer fonctionne ici suivant 2 alternances consécutives de durées inégales, mais dont la somme est constante
;on obtient dont une fréquence constante avec un rapport cyclique variable
;valeur max de rapcycl admissible =253 (avec prediv =1/8 (voir T1CON))

inttimer1	movlw	B'00000010'
	xorwf	mesflags,f	;inverse le flag de phase

	btfsc	mesflags,1	;test du flag de phase
	goto	int1_a

	movf 	rapcyc1,w		;ici w=rapcycl
	sublw	.255		;ici w=255-rapcycl
	movwf	TMR1L
	movlw	0xFF		;pour utiliser le timer1 sur 8 bits seulement
	movwf	TMR1H
	
	goto	int1_b

int1_a	movf 	rapcyc1,w
	movwf	TMR1L
	movlw	0xFF
	movwf	TMR1H
	
	btfsc	mesflags,0	;STOP ?
	goto	int1_b		;oui, on va bloquer le MOSFET

	bsf	PORTB,1		;SORTIE PHYSIQUE sur le port B pour commander le MOSFET voie ANTI-COUPLE
	return

int1_b	bcf	PORTB,1		;SORTIE PHYSIQUE sur le port B pour commander le MOSFET voie ANTI-COUPLE	

fin_int1	return



;----------------------------------------------------------------------
;int timer2
;génération du signal de sortie VOIE GAZ
;ce timer fonctionne ici suivant 2 alternances consécutives de durées inégales, mais dont la somme est constante
;on obtient dont une fréquence constante avec un rapport cyclique variable
;valeur max de rapcycl admissible =253 (avec prediv =1/16 (voir T2CON))
;attention: si prediv<1/16 ou si rapcycl > 253 alors-> int Timer2 = HS (pas le temps de réinitialier PR2)

inttimer2	movlw	B'00000100'
	xorwf	mesflags,f	;inverse le flag de phase

	btfsc	mesflags,2	;test du flag de phase
	goto	int2_a

	movf 	rapcyc2,w		;ici w=rapcycl
	sublw	.255		;ici w=255-rapcycl

	BANK1
	movwf	PR2		;PR2 = registre 8bits de période du Timer2 situé en banque1
	BANK0
	
	goto	int2_b

int2_a	movf 	rapcyc2,w

	BANK1
	movwf	PR2		;PR2 = registre 8bits de période du Timer2
	BANK0

	btfsc	mesflags,0	;STOP ?
	goto	int2_b		;oui, on va bloquer le MOSFET

	bsf	PORTB,2		;SORTIE PHYSIQUE sur le port B pour commander le MOSFET VOIE GAZ
	return

int2_b	bcf	PORTB,2		;SORTIE PHYSIQUE sur le port B pour commander le MOSFET VOIE GAZ	
fin_int2	return


;----------------------------------------------------------------------
;int Extérieure par bit 0 du port B
;sert à detecter les fronts du signal PPM du récepteur de radio-commande, voie GAZ
;et à mesurer la durée du signal à 1 


intB0	btfss	mesflags,4	;quel front vient-on de détecter ?
	goto	frontD0		;le front descendant
	
frontM0	clrf	TMR0		;le front montant. 	RAZ Timer0
	BANK1
	bcf	OPTION_REG,6	;Interrupt on falling edge of RB0/INT pin (détectera le front descendant)
	BANK0
	bcf	mesflags,4	;pour éviter une lecture en bank1 au début de cette procédure, on testera ce flag
	return

frontD0	movf	TMR0,w		;le timer0 à compté (l'horloge du PIC) depuis le front montant précédent
	movwf	T_PPM_G		;MEMORISATION DE LA MESURE DU SIGNAL PPM voie GAZ pour le reste du programme
	BANK1
	bsf	OPTION_REG,6	;(détectera le front montant)
	BANK0
	bsf	mesflags,4
	clrf	TMR0
	return
;----------------------------------------------------------------------
;int Extérieure par bit5 du port B
;sert à détecter les fronts du signal PPM du récepteur de radio-commande, voie ANTI-COUPLE
;et à mesurer la durée du signal à 1
;REMARQUE: contrairement à l'intRB0, les INT RB4-7 sont déclenchées par les fronts montants ET descendants
;sans que l'on puisse choisir lequel
;Mais en fait ceci aboutit à simplifier la procédure
;lorsque l'int est déclenchée, il suffit de tester l'état du port pour savoir si elle a été déclenchée par un
;front montant ou descendant.
;REMARQUE2: Cette procédure utilise volontairement LE MEME timer (le Timer0) que la précédente (intB0)
;ceci est possible car les signaux PPM des différentes voies ne sont jamais simultanés, mais sont succéssifs.
;Donc les comptages des temps par le Timer0 ne se chevauchent pas (voir plus bas la précaution à prendre)
;ET AINSI ON GAGNE UN TIMER !
;(on peut éenddre ce principe pour un plus grand nombre de voies ! avec 1 seul timer, on peut mesurer
;autant de périodes de temps qu' on veut, pourvu qu' elles soient disjointes)

;************* ATTENTION ****************
;Pour éviter un RAZ intempéstif du Timer0 d'une voie par l'autre,
;LES VOIES GAZ ET ANTI-COUPLE NE DOIVENTS PAS ETRE 2 VOIES CONSECUTIVES SUR LA RADIO !!!
;choisir par exemple les voies 2et4 MAIS PAS les voies 3et4 ou 2et3 pour l'anti-couple et les gaz.
;****************************************


intB5	btfss	PORTB,5	;quel front vient-on de détecter ?
	goto	frontD5	;le front descendant
	
frontM5	clrf	TMR0	;le front montant. 	RAZ Timer0
	return

;le timer1 à compté (l'horloge du PIC) depuis le front montant précédent
frontD5	movf	TMR0,w	;le timer0 à compté (l'horloge du PIC) depuis le front montant précédent
	movwf	T_PPM_A	;MEMORISATION DE LA MESURE DU SIGNAL PPM voie A.Couple pour le reste du programme

	clrf	TMR0
	return




;------------------------------------------------------------------------
;Pour test seulement: mémorise en EEPROM les valeurs simultanées de la vitesse Rotor et AntiCouple
;afin d'étudier la courbe obtenue (sous Excel par exemple)

ecrireEE	movf	adrEE,w
	movwf	DDD
	movf	rapcyc2,w
	W_EEPROM	
	incf	adrEE,f
	
	movf	adrEE,w
	movwf	DDD
	comf	rapcyc1,w
	W_EEPROM	
	incf	adrEE,f
	
	call	tp100ms	;anti-rebond
	call	tp100ms
	call	tp100ms
	call	tp100ms
	call	tp100ms
	return



;************************************************************************
;début des procédures d'affichage LCD (utilisent le portA)
;************************************************************************

;FUNCTION SET

fset	bcf	PORTA,2	;E=0
	bcf	PORTA,3	;R/S=0

	movlw	.56	;(32+16+8)
	movwf	dtlcd	

	call 	dt_out	;transmission série vers 4015 -> DATA // LCD
	call 	impuls
	return
;----------------------------------------------------------------------
;DISPLAY CLEAR
dspclr	bcf	PORTA,2	;E=0
	bcf	PORTA,3	;R/S=0

	movlw	.1
	movwf	dtlcd
	call 	dt_out
	call 	impuls
	return
;----------------------------------------------------------------------
;RETURN HOME
home	clrf	PORTA
	movlw	.2
	movwf	dtlcd
	call 	dt_out
	call 	impuls
	return

;----------------------------------------------------------------------
;ENTRY MODE SET 0
;le curseur se déplace

setmod0	bcf	PORTA,2	;E=0
	bcf	PORTA,3	;R/S=0
	
	movlw	.6	;( 4+2 sens inverse si 4+0 )	
	movwf	dtlcd
	call 	dt_out
	call 	impuls
	return
;----------------------------------------------------------------------
;ENTRY MODE SET 1
;curseur gelé
setmod1	bcf	PORTA,2	;E=0
	bcf	PORTA,3	;R/S=0

	movlw	.7	;( 4+2+1 )	
	movwf	dtlcd
	call 	dt_out
	call 	impuls
	return

;----------------------------------------------------------------------
;DISPLAY ON OFF
dsp10	bcf	PORTA,2	;E=0
	bcf	PORTA,3	;R/S=0

	movlw	.12	;( 8+4 )	
	movwf	dtlcd
	call 	dt_out
	call 	impuls
	return
;----------------------------------------------------------------------
;DDRAM ADRESS SET (A)
;w doit contenir l'adresse (position d'affichage. voir doc)
ddras	bcf	PORTA,2	;E=0
	bcf	PORTA,3	;R/S=0
	addlw	.128
	movwf	dtlcd
	call 	dt_out
	call 	impuls
	return
;----------------------------------------------------------------------
;CURSOR OR DISPLAY SHIFT
;DEFILEMENT DU TEXTE
shiftT	bcf	PORTA,2	;E=0
	bcf	PORTA,3	;R/S=0

	movlw	.24	;( 16+8 )	
	movwf	dtlcd
	call 	dt_out
	call 	impuls
	return
;----------------------------------------------------------------------
;CURSOR OR DISPLAY SHIFT
;DEFILEMENT DE LA POSITION D'AFFICHAGE (CURSEUR)
shiftC	bcf	PORTA,2	;E=0
	bcf	PORTA,3	;R/S=0

	movlw	.16	;( 16 )	
	movwf	dtlcd
	call 	dt_out
	call 	impuls
	return

;----------------------------------------------------------------------
;ECRIRE
;w doit contenir lavaleur ASCII du caractère à afficher
ecrire	bcf	PORTA,2	;E=0
	bsf	PORTA,3	;R/S=1

	movwf	dtlcd
	
	call 	dt_out

	bsf	PORTA,2		;impuls E à 1 avec RS=1
	call 	tp10ms
	bcf	PORTA,2		;fin impulsion
	call 	tp10ms
	return

;----------------------------------------------------------------------
;impulsion E à 1 avec RS=0
impuls	bcf	PORTA,3		;R/S=0
	bsf	PORTA,2		;impulsion E à 1
	call 	tp10ms
	bcf	PORTA,2		;fin impulsion
	call 	tp10ms
	return

;----------------------------------------------------------------------
;SORTIE DATA (8 bits) en série sur PA0 vers CD4015. PA1=Clock 4015.

dt_out	movlw	.8
	movwf	bitn
dtbcl	rlf	dtlcd,f
	bcf	PORTA,0		;bit = 0 (à priori)
	btfsc	STATUS,0	;test carry
	bsf	PORTA,0		;non,  bit = 0

out	bsf	PORTA,1		;clock 4015
	call	tp154us
	bcf	PORTA,1		;fin clock
	call	tp154us
	decfsz	bitn,f	
	goto	dtbcl
	return


;------------------------------------------------------------------------
affi4	movf	aff4,w
	addlw	.48	;code ASCII de zéro
	call 	ecrire

affi3	movf	aff3,w
	addlw	.48	;code ASCII de zéro
	call 	ecrire
	
affi2	movf	aff2,w
	addlw	.48	;code ASCII de zéro
	call 	ecrire

	movf	aff1,w
	addlw	.48	;code ASCII de zéro
	call 	ecrire


	return



;------------------------------------------------------------------------
;nb decimaux dans AA(unités) et BB(centaines) au préalable
affdeci	movf	BB,w
	movwf	CC	;memo BB danc CC because cvBDU utilise BB
	call 	cvBDU
	movf	AA,w	;ld A,V
	movwf	aff1	;ld Aff1,A
	movf	BB,w	;ld A,W
	movwf	aff2	;ld Aff2,A
	
	movf	CC,w	;ld A,BB	;0..99
	movwf	AA
	call 	cvBDU
	movf	AA,w
	movwf	aff3
	movf	BB,w
	movwf	aff4	
	return

;-----------------------------------------------------------------------
;affiche un octet complet sur aff1..4 (4 TIL 702)
;W doit contenir l'octet à afficher
affiw	movwf	AA
	call 	cvBDU	;BB=18 et AA=4
	movf	AA,w
	movwf	aff1	;aff1=4

	movf	BB,w	;w=18
	movwf	AA	;AA=18
	call 	cvBDU	;BB=1 et AA=8
	
	movf	AA,w
	movwf	aff2	;aff2=8
	movf	BB,w
	movwf	aff3	;aff3=1
	
	clrf	aff4
	call	affi4
	return

;-----------------------------------------------------------------------
;affichage nombre 0..9999
;AH et AL contiennent un nb 0..9999
affnb	movf	AL,w	;ld A,AL
	movwf	AA
	call 	cvBCU	;convertit period0 en BCD
;résultat dans AA(unités) et BB(centaines)		

;on va ajouter valbin1 x 256

	movf	AH,w	;ld A,AH
	movwf	DD		;ld memo3,A pour'pas toucher period1

	incf 	DD,f	;hors boucle
afn1	decfsz 	DD,f
	goto 	saut1		;jrnz ici1
	goto 	suitef
				;ld A,AA
saut1	movlw	.56
	addwf	AA,f	;addi A,56 (+56) retenue decimale possible
	movf	AA,w
	sublw	.99		;carry =0 si AA>99
	btfsc	STATUS,0	;bit de carry
	goto st1	;donc saut->conv3 si carry=1, c.a.d si A>99
				;jrc st1
	movlw	.100
	subwf 	AA,f
	incf 	BB,f	;ajout retenue decimale

st1	movlw	.2
	addwf	BB,f	;(+200) soit en tout +256
		
	goto 	afn1

suitef	call 	affdeci
	return

;------------------------------------------------------------------------

;CONVERSION BINAIRE(1) (1 octet incomplet 0..99 et pas 0..255) --> BCD
;nombre à convertir dans AA
;resultat dans BB (dizaines) et dans AA (unités)
;ex: AA=237 -> BB=23 et AA=7
;ex2 AA=84  -> BB=8  et AA=4

cvBDU	clrf	BB

conv2	movlw	.10
	subwf	AA,w	;w=AA-10 positionne le bit de carry si A<10
	btfss	STATUS,0	;bit de carry
	goto 	conv3	;donc saut ->conv3 si carry=1, c.a.d si A<10
	movlw	.10
	subwf 	AA,f	;en boucle : revient à diviser A par 10
	incf	BB,f
	goto 	conv2	;9 passages au max si nb <= 99
conv3	return

;--------------------------------------------------------------------
;CONVERSION BINAIRE(2) (1 octet complet 0..255) --> BCD
;nombre à convertir dans AA
;resultat dans BB (centaines) et dans AA (unités)
;ex: AA=237 -> BB=23 et AA=7

cvBCU	clrf	BB

conv4	movlw	.100
	subwf	AA,w	;w=AA-100 positionne le bit de carry si A<100
	btfss	STATUS,0	;bit de carry
	goto 	conv5	;donc saut ->conv3 si carry=1, c.a.d si A<100
	movlw	.100
	subwf 	AA,f	;en boucle : revient à diviser A par 100
	incf	BB,f
	goto 	conv4	;9 passages au max si nb <= 999
conv5	return


;--------------------------------------------------------------------



;***********************************************************************
; ROUTINES MATH
;***********************************************************************

;------------------------------------------------------------------------
;conversion sexadécimale -> binaire
;entrée: AA, BB
;resultat: AH,AL = 60*AA+BB

convhbin	movlw	.60
	call	multi	;AA contient la donnée à multiplier
	movf	BB,w
	addwf	AL,f	
	btfsc	STATUS,0	;carry
	incf	AH,f
	return

;------------------------------------------------------------------------
;mutiplication 8 bits x 8 bits de AA par w (données sur 1 octet)
;d'après note AN526 Microchip
;resultat (sur 2 octets) dans AH,AL (poids fort et poids faible)
multi	clrf	AH
	movwf	AL
	movlw	.8
	movwf	count1
	movf	AL,w
	clrf	AL
	bcf	STATUS,0	;RAZ carry
loop	rrf	AA,f
	btfsc	STATUS,0
	addwf	AH,f
	rrf	AH,f
	rrf	AL,f
	decfsz	count1,f
	goto	loop
	return

;------------------------------------------------------------------------
;division d'une valeur codée sur 16 bits (AH,AL) par 2
divi2	bcf	STATUS,0	;RAZ carry c=0
	rrf	AH,f	;le bit de poids faible tombe dans -> c ; le bit de poids fort de AH devient nul
	rrf	AL,f	;le bit de poids faible de AH devient le bit de poids fort de AL
	return
		
;------------------------------------------------------------------------
;	addwf	AL,f	;(f+w) -> dest ; c=1 si retenue (à traiter)
	btfsc	STATUS,0	;c
	incf	BH,f	;ajout retenue
	movf	BH,w
	addwf	AH,f	;(f+w) -> dest ; c=1 si retenue
	return

;------------------------------------------------------------------------
;addition 16bits
;(AH,AL)+(AH,AL) -> (BH,BL)
;remarque seule la destination (B) est différente par rapport à la procédure add16A
add16B	movf	AL,w
	addwf	BL,f	;(f+w) -> dest ; c=1 si retenue (à traiter)
	btfsc	STATUS,0	;c
	incf	AH,f	;ajout retenue
	movf	AH,w
	addwf	BH,f	;(f+w) -> dest ; c=1 si retenue
	return

;------------------------------------------------------------------------
;complément à deux de la variable codée sur 2 octets situés aux adresses w et w+1
cpl16x	movwf	FSR
	comf	INDF,f	;w=complément (H)
	incf	FSR,f
	comf	INDF,f	;w=complément (L)
	incf	INDF,f	;w=complément à 2 de L
	btfss	STATUS,2	;z
	return	
	decf	FSR,f	;pointe H
	incf	INDF,f	;retenue
	return
;------------------------------------------------------------------------
;division 16bits par 8 bits résultat sur 8 bits : BH,L / w -> w
;par approximations succésives sur les 8 bits (méthode rapide, 8 passages max dans la boucle)
;ATTENTION si le résultat est >255  il sera retourné = 255
;il est évident par exemple que 65535 / 1 = 65535 ne tient pas sur 1 octet
;toutefois dans ce programme, le résultat est borné sur 1 octet
; x/0 donne 255
; 0/0 donne 255
; 0/x (x<>0) donne 0


divi16_8	movwf	CC	;CC contient le diviseur
	clrf	BB
	movlw	B'10000000';masque du bit testé
	movwf	DD
	movwf	BB
	

divi1	movf	CC,w
	movwf	AA

	movf	BB,w
	call	multi	;AH,L=AA*w = diviseur * BB	;ne touche pas 
	call	compar16p	;ne touche pas AA ni BB
	btfss	STATUS,0
	goto	trop	;test bit suivant
	goto	pastrop
	
	decf	BB,w	;résultat
	return	

trop	movf	DD,w
	xorwf	BB,f	;éteint le bit précédent
	bcf	STATUS,0
	rrf	DD,f	;bit suivant
	btfsc	STATUS,0	;c 	c'était le dernier ?
	goto	findiv	;	oui
	movf	DD,w
	iorwf	BB,f	;allume le bit suivant
	goto	divi1
	
pastrop	bcf	STATUS,0
	rrf	DD,f	;bit suivant
	btfsc	STATUS,0	;c 	c'était le dernier ?
	goto	findiv	;	oui
	movf	DD,w
	iorwf	BB,f	;allume le bit suivant
	goto	divi1	

findiv	movf	BB,w
	return
	
	
;------------------------------------------------------------------------
;mov la variable codée sur 2 octets situés aux adresses w et w+1  dans -> AH,AL
movxA	movwf	FSR
	movf	INDF,w
	movwf	AH
	incf	FSR,f
	movf	INDF,w
	movwf	AL
	return	
;------------------------------------------------------------------------
;mov AH,AL dans -> la variable codée sur 2 octets situés aux adresses w et w+1  
movAx	movwf	FSR
	movf	AH,w
	movwf	INDF
	incf	FSR,f
	movf	AL,w
	movwf	INDF
	return
;------------------------------------------------------------------------
;mov la variable codée sur 2 octets situés aux adresses w et w+1  dans -> BH,BL
movxB	movwf	FSR
	movf	INDF,w
	movwf	BH
	incf	FSR,f
	movf	INDF,w
	movwf	BL
	return	
;------------------------------------------------------------------------
;mov BH,BL dans -> la variable codée sur 2 octets situés aux adresses w et w+1  
movBx	movwf	FSR
	movf	BH,w
	movwf	INDF
	incf	FSR,f
	movf	BL,w
	movwf	INDF
	return

;------------------------------------------------------------------------
;comparaison de deux valeurs codées sur 16 bits (AH,AL à BH,BL)
;resultat dans STATUS carry et zéro
;les valeurs doivent représenter des nombres tous deux positifs (pas ok si valeurs codées en complément à 2)
;sauf pour le test d'égalité STATUS,2 ('z')
;16p-> p comme positifs

compar16p	movf	AH,w
	subwf	BH,w	;c=0 si AH>BH
	btfss	STATUS,2	;z=1 si AH=BH il faut alors comparer AL à BL
	return
	movf	AL,w
	subwf	BL,w	;z=1 si AL=BL et comme on sait déjà que AH=BH, si z=1 -> A=B
	return

;------------------------------------------------------------------------





;***********************************************************************
; TEMPOS GENERALES
;***********************************************************************

; Qx = 20,000 Mhz
;TEMPO 154us pile
;tiens compte du call de l'appelant et du return final

tp154us	movlw	.255	;1 cycle
	movwf	t1	;1 cycle

t3loop1	decfsz	t1,f	;1 cycle
	goto	t3loop1	;2 cycles

	return		;2 cycles

;----------------------------------------------------------------------
; Qx = 20,000 Mhz
; 2,0004ms
;tiens compte du call de l'appelant et du return final

tp2ms	movlw	.13
	movwf	t1

t4loop1	movlw	.255
	movwf	t2

t4loop2	decfsz	t2,f
	goto	t4loop2
	decfsz	t1,f
	goto	t4loop1
	return
;----------------------------------------------------------------------
; Qx = 20,000 Mhz
; 1,000ms
;tiens compte du call de l'appelant et du return final

tp1ms	movlw	.11
	movwf	t1

t5loop1	movlw	.150
	movwf	t2

t5loop2	decfsz	t2,f
	goto	t5loop2
	decfsz	t1,f
	goto	t5loop1
	return
;----------------------------------------------------------------------
; Qx = 20,000 Mhz
; 9,998ms
;tiens compte du call de l'appelant et du return final

tp10ms	movlw	.65
	movwf	t1

t1loop1	movlw	.255
	movwf	t2

t1loop2	decfsz	t2,f
	goto	t1loop2
	decfsz	t1,f
	goto	t1loop1
	return

;----------------------------------------------------------------------
; Qx = 20,000 Mhz

tp100ms	clrwdt
	movlw	.10
	movwf	t3

t2loop2	clrwdt
	call 	tp10ms
	decfsz	t3,f	
	goto 	t2loop2
	return

;----------------------------------------------------------------------
; Qx = 20,000 Mhz
;tempo n x 10ms
;charger w avec n avant l'appel de cette procédure
;
tx10ms	movwf	t3

txlp2	call 	tp10ms
	decfsz	t3,f	
	goto 	txlp2
	return
;----------------------------------------------------------------------
; Qx = 20,000 Mhz
;tempo n x 1ms
;charger w avec n avant l'appel de cette procédure
;
tx1ms	movwf	t3

txlp3	call 	tp1ms
	decfsz	t3,f	
	goto 	txlp3
	return





;***********************************************************************
; TABLEAUX DE DONNEES
;***********************************************************************

;NOTE: les tableaux doivent se situer chacun sur 1 seule page d'adresse codée sur 8 bits (longueur<=255, 00FF h)
;c.a.d qu'un tableau ne doit pas être à cheval sur dex pages
;verifier sur le listing absolu obtenu après compilation.
;je le place en page6
;NOTE: en exa, chaque page de 256octets = 100 (noté 0x100)
;RAM page1=0000 à 00FF
;RAM page2=0100 à 01FF
;RAM page3=0200
;etc... jusqu'à 
;RAM page8=0700 à 07FF (8 pages de 256 octets pour le PIC16F628, soit 2kO RAM) 

	org	07C0h

;Le datasheet de Microchip précise ceci:

;A computed GOTO is accomplished by adding an offset
;to the program counter (ADDWF PCL). When doing a table
;read using a computed GOTO method, care should be
;exercised if the table location crosses a PCL memory
;boundary (each 256 word block). Refer to the application
;note "Implementing a Table Read" (AN556).






;--------------------------fin des tableaux en FLASH -----------------------------------


;=======================================================================================
;DATA EN EEPROM
;=======================================================================================


	ORG 0x2100 ; zone EEPROM 


	
;=======================================================================================
	end


