#device pic16f628
//**************************************************************************************************************
// Programme de gestion de la carte SURFACE Explobotique / VERSION 1.0 du 5/3/2006
// pour tout renseignements : explobotique@free.fr ou forum sur http://explobotique.free.fr
// Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier au titre des
// clauses de la Licence Publique Generale GNU, telle que publiee par la Free Software Foundation ; soit la
// version 2 de la Licence, ou (a votre discretion) une version ulterieure quelconque. Ce programme est
// distribue dans l'espoir qu'il sera utile, mais SANS AUCUNE GARANTIE ; sans meme une garantie implicite de
// COMMERCIABILITE ou DE CONFORMITE A UNE UTILISATION PARTICULIERE. Voir la Licence Publique Generale GNU pour
// plus de details. Vous devriez avoir recu un exemplaire de la Licence Publique Generale GNU avec ce programme
// si ce n'est pas le cas, ecrivez a la Free Software Foundation Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// vous pouvez consulter la licence sur  : http://www.gnu.org/copyleft/gpl.html
// ou sa traduction (non officielle) sur : http://fsffrance.org/gpl/gpl-fr.fr.html
//**************************************************************************************************************

#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT,NOMCLR,NOLVP
#use delay (clock=4000000)


#include <stdlib.h>



#byte PORTA = 5
#byte PORTB = 6
#byte PIR1  = 0x0C
#byte TMR1L = 0x0E
#byte TMR1H = 0x0F
#byte T1CON = 0x10
#byte CMCON = 0x1F

#byte TRISA = 0x85
#byte TRISB = 0x86
#byte INTCON = 0x0B

#byte OPTION =0x81

#bit	TIMER1_OVR = PIR1.0	/* Timer 1 overflow */
#bit	TIMER1_EN = T1CON.0	/* Validation timer 1 */

// port serie
#byte PIE1=0x8C         // registre de validation des IT

#byte SPBRG=0x99        // registre baud rate
#byte TXREG=0x19        // registre de transmission
#byte RCREG=0x1A        // registre de reception
#byte TXSTA=0x98        // transmit status and ctrl TX
#byte RCSTA=0x18        // transmit status and ctrl RX + global



/* Affectation des E/S :

   RA0   S   DB4 LCD
   RA1   S   DB5 LCD
   RA2   S   DB6 LCD
   RA3   S   DB7 LCD
   RA4   S   RS LCD
   RA5   E   DO Convertisseur A/D ADC 0838
   RA6   S   OSC2  16F628
   RA7   E   OSC1  16F628

   RB0   S   TE MAX 487
   RB1   E   RS MAX 487
   RB2   S   TIN  MAX 487
   RB3   S   ENABLE LCD
   RB4   S   A 4052 / CLX ADC 0838
   RB5   S   B 4052 / DI ADC 0838
   RB6   S   INH 4052 / CS ADC 0838
   RB7   S   SORTIE ALARME BUZZER / LED
*/

/* variables globales */

unsigned long int I ;
unsigned char BITS ;	/* stockage de differents bits */

unsigned char LCD_BUF[18] ; /* Buffer pour ecriture LCD */

// tension batterie surface et fond
unsigned char VBAT_SURF ;
#define	VSURF_MIN	115	// 11,5 Volts
unsigned char VBAT_FOND ;
#define	VFOND_MIN	230	// 23 Volts


/* E/S et definitions de l'afficheur LCD */
#bit	LCD_RS = PORTA.4	/* A4 LCD */
#bit	LCD_EN = PORTB.3	/* CS LCD */

#define  LCD_L0   0     /* adresse debut ligne 0 */
#define  LCD_L1   64    /* adresse debut ligne 1 */
#define  LCD_L2   16    /* adresse debut ligne 2 */
#define  LCD_L3   80    /* adresse debut ligne 3 */

#define	LCD_STROBE	{ LCD_EN = 1 ; LCD_EN=0 ; }

/* E/S de l'ADC0838 */
#bit	ADC_CS = PORTB.6	/* chip select (commun avec 4052) */
#bit	ADC_DI = PORTB.5	/* entree data ADC */
#bit	ADC_DO = PORTA.5	/* sortie data ADC */
#bit	ADC_CK = PORTB.4	/* horloge ADC */

/* Bits E/S et valeurs des BP */
#bit	BP_MUXA = PORTB.4	/* entree A  MUX */
#bit	BP_MUXB = PORTB.5	/* entree B  MUX  */
#bit	BP_STATE = PORTA.5	/* etat BP ( sortie MUX ) */

#bit	BUZZER = PORTB.7	/* commande du buzzer */

#define  BP_VALID    0X04
#define  BP_SPOT     0x02
#define  BP_CAMERA   0x01
#define  BP_ACQUIT   0X08





/* definitions diverses */
#define  VRAI  1
#define  FAUX  0

#define  STX   0x02
#define  ETX   0x03

#define  RAZDOG   #asm CLRWDT #endasm // raz du watchdog




/* prototype des fonctions */
void lcd_goto(unsigned char pos) ;


//****************************************************************************
// gestion liaison serie

// Taille des buffers
#define  TAILLE_BUF_TX  17
#define  TAILLE_BUF_RX  15

// nombre de caractere de la reponse carte UC video
#define	TAILLE_REP_UCVID	5

#define  VALIDE_TX      PORTB|= 0x01
#define  DEVALIDE_TX    PORTB&=~0x01


// variable pour stats sur transmission
unsigned char NB_TRAME_EMIS ;
unsigned char NB_TRAME_OK ;
unsigned char QUALITE_TRANS ;

// VARIABLES ET DEFINITIONS CARTE UC VIDEO ******************

// commande de la carte UC video
#define CDE_UC_VIDEO	0x20
#define TAILLE_CDE_UCVIDEO	16
#define  NB_CAMERAS  1  	// valeur IMPERATIVEMENT entre 1 et 4

// valeur des pulses pour les variateurs
#define P_NEUTRE	62	// 1 mS
#define P_MIN 		31	// 0,5 mS
#define P_MAX 		94	// 1,5 mS

// variables de la carte UC VIDEO
unsigned char MOT_D ;	// valeur de commande du moteur droit
unsigned char MOT_G ;	// valeur de commande du moteur gauche
unsigned char MOT_V ;	// valeur de commande du moteur vertical
unsigned char IO_UCVIDEO;	// melange de commandes phares et selection camera
unsigned char ETAT_UCVIDEO;// variable d'etat renvoye par la carte

// VARIABLES DIVERSES ***************************************
unsigned char FLAGS ;	// flags divers

// CDE et NO module ( sous-commande )
unsigned char  CDE ;  	// commande en cours
unsigned char  SS_CDE ;	// sous-commande en cours

unsigned char BUF_TX[TAILLE_BUF_TX] ;     // Buffer de transmission
unsigned char IND_TX ;                    // indice du prochain caractere a transmettre
unsigned char NB_RESTANT_TX ;             // nombre de caractere restant a transmettre

unsigned char BUF_RX[TAILLE_BUF_RX] ;     // Buffer de reception
unsigned char IND_RX ;                    // indice du prochain caractere a recevoir
unsigned char NB_CAR_TRAME_RX ;           // nombre de caractere a recevoir
unsigned char CKSM_RX ;                   // cksum reception
#bit FLAG_TRAME_EN_COURS=FLAGS.0          // vrai si on a vu un STX et jusqu'a  fin traitement reception


// joystick
unsigned char MANCHE_X ;      // valeur manche en X
unsigned char MANCHE_Y ;      // valeur manche en Y
unsigned char MANCHE_Z ;      // valeur manche en Z
unsigned char NEUTRE_X ;      // valeur neutre X
unsigned char NEUTRE_Y ;      // valeur neutre en Y
unsigned char NEUTRE_Z ;      // valeur neutre en Z

signed int16 X,Y,T ;          // pour calculs manches

#define MAX_MANCHE   31       // variation maxi des manches autour du neutre ( en + et - )


unsigned char ETAT_BP ;       // etat des poussoir
unsigned char ETAT_BP_PRECED; // etat precedent des poussoir

// phares et camera
unsigned char CAMERA ;        // no camera en cours ( 0 - 3 )
unsigned char PHARES ;        // 2 bits de cde phares

// buzzer et alarme
#bit FLAG_ACQUIT=FLAGS.1      // vrai si on doit commander le buzzer
#bit FLAG_ALARME=FLAGS.2      // vrai si une alarme est active


//----------------------------------------------------------------------------
// fonction d'init de la communication serie
//----------------------------------------------------------------------------
void INIT_SERIE(void)
{
// init variables
IND_RX=0 ;
NB_RESTANT_TX=0 ;
FLAG_TRAME_EN_COURS=FAUX ;
NB_TRAME_EMIS=0 ;
NB_TRAME_OK=0 ;
QUALITE_TRANS=100 ;	// pour ne pas declencher l'alarme a l'init

// configure vitesse de transmission ( quartz 4MHz / 19200 Bauds )
SPBRG=12 ;

// valide mode asynchrone / high baud rate / 8bits / TX,RX enable
TXSTA=0x24 ;
RCSTA=0x90 ;

// valide IT reception
PIE1|=0x20 ;
}

//----------------------------------------------------------------------------
// fonction de lancement d'une transmission de n caracteres
//----------------------------------------------------------------------------
void LANCE_TX(unsigned char n)
{
// demande impossible : pas d'action
if( n>TAILLE_BUF_TX ) return ;

// deja une transmission en cours : pas d'action
if( NB_RESTANT_TX!=0)   return ;

// active le transmetteur
VALIDE_TX ;

IND_TX=1 ;
NB_RESTANT_TX=n ;

// envoi le premier caractere
TXREG=BUF_TX[0] ;

// valide les IT TX
PIE1|=0x10 ;

// gestion des stats
if( ++NB_TRAME_EMIS == 100)
	{
	QUALITE_TRANS=NB_TRAME_OK ;
	NB_TRAME_EMIS=0 ;
	NB_TRAME_OK=0 ;
	}
}


//----------------------------------------------------------------------------
// fonction de preparation d'une commande pour la carte UC VIDEO
//----------------------------------------------------------------------------
void PREPARE_CDE_UCVIDEO( void )
{
char i ;
unsigned char cksm ;

CDE=CDE_UC_VIDEO+0x80 ;	// toujours demande de reponse
SS_CDE=0 ;
cksm=0 ;

BUF_TX[0]=0x55 ;     // bourrage
BUF_TX[1]=STX ;
BUF_TX[2]=CDE ;
BUF_TX[3]=SS_CDE ;

// commande phares , selection video et delai reponse ( 1 ms )
IO_UCVIDEO=((CAMERA*4)+PHARES)*16 ;
BUF_TX[4]=IO_UCVIDEO | 0x01 ;

// valeur des 8 pulses servo
BUF_TX[5]= MOT_V ;
BUF_TX[6]= MOT_D ;
BUF_TX[7]= P_NEUTRE ;
BUF_TX[8]= MOT_G ;
BUF_TX[9]= P_NEUTRE ;
BUF_TX[10]=P_NEUTRE ;
BUF_TX[11]=P_NEUTRE ;
BUF_TX[12]=P_NEUTRE ;

// calcul cksm
for(i=2 ; i<13 ; i++ )
	cksm+=BUF_TX[i] ;


BUF_TX[13]=~cksm ;
BUF_TX[14]=ETX ;
BUF_TX[15]=0x55 ;

}



//----------------------------------------------------------------------------
// TRAITEMENT de la trame recue
// la trame est deja controle et correcte , seule la commande n'est pas testee
//----------------------------------------------------------------------------
void TRAITE_RX(void)
{
char i ;

// controle commande et sous-commande
if( ((BUF_RX[0]&0x7F)!=(CDE&0x7F)) || (BUF_RX[1]!=SS_CDE) )
	return ; // pas pour nous !

//recuperation de l'etat de la carte
ETAT_UCVIDEO=BUF_RX[2] ;

NB_TRAME_OK++ ;

}

//----------------------------------------------------------------------------
// interruption de transmission ACIA
//----------------------------------------------------------------------------
#INT_TBE
IT_TX(void)
{

if( NB_RESTANT_TX==0)
	{
	PIE1&=~0x10 ;     // devalide les IT TX
	DEVALIDE_TX ;     // devalidation du transmetteur
	}
else if( NB_RESTANT_TX==1)
	{
	// on transmet un caractere bidon (0) pour garder actif le signal
	// de validation du transmetteur pendant le decalage du dernier caractere
	NB_RESTANT_TX=0 ;
	TXREG=0 ;
	}
else
	{
	// transmet le caractere
	TXREG=BUF_TX[IND_TX] ;
	IND_TX++ ;
	NB_RESTANT_TX-- ;
	}
}

//----------------------------------------------------------------------------
// interruption de reception ACIA
//----------------------------------------------------------------------------
#INT_RDA
IT_RX(void)
{
// controle des erreurs
if((RCSTA&0x06)!=0 )
	{     // en cas d'erreur on abandonne la reception en cours
	FLAG_TRAME_EN_COURS=FAUX ;
	// raz overrun
	RCSTA&=~0x10 ; RCSTA|=0x10 ;
	// raz framing error
	BUF_RX[0]=RCREG ;
	return ;
	}

if(!FLAG_TRAME_EN_COURS)    // pas encore en reception
	{
	if(RCREG==STX)          // debut de trame ?
		{
		IND_RX=0 ;
		NB_CAR_TRAME_RX=4 ;              // trame mini !
		CKSM_RX=0 ;
		FLAG_TRAME_EN_COURS=VRAI ;
		}
	}
 else                      // deja en reception
	{
	BUF_RX[IND_RX]=RCREG ;     // lecture et stockage caractere
	CKSM_RX+=BUF_RX[IND_RX] ;  // calcul cksm
	IND_RX++ ;

	if(IND_RX==1)  // le 1er caractere recue est la cde => donne la longueur
		{
		NB_CAR_TRAME_RX=TAILLE_REP_UCVID ; // dans ce cas une seule commande => longueur constante
		}

	else if(IND_RX>=NB_CAR_TRAME_RX)  // fin de reception ?
		{  // oui , controle et traitement
		// presence de la fin de trame
		if(BUF_RX[IND_RX-1]!=ETX)
			{  // NON => trame non valide
				FLAG_TRAME_EN_COURS=FAUX ;
				return ;
			}

		// controle CKSUM
		CKSM_RX-=ETX ;          // on retire le caractere ETX
		if(CKSM_RX!=0xFF)    // et on controle
			{  // ERREUR CKSM => trame non valide
				FLAG_TRAME_EN_COURS=FAUX ;
				return ;
			}

		// traitement de la trame dans l'IT
		TRAITE_RX() ;

		FLAG_TRAME_EN_COURS=FAUX ;
		}


   }
}



/*--------------------------------------------------------------------*/
void DelayUs(unsigned char x)
{
x/=2 ;
 while(--x)
   {
   #asm
	  nop
   #endasm
   }
}

/*----------------------------------------------------------------------------*/
void DelayMs(unsigned char n)
{
unsigned long int t ;

for(;n;n--)
	{
	for(t=0;t<88;t++)	/* boucle 1 ms */
		{
	    #asm
	        nop
      #endasm
		}
	}
}

/*--------------------------------------------------------------------*/
/* write a byte to the LCD in 4 bit mode */

void lcd_write(unsigned char c)
{
	PORTA &= 0xF0 ;
	PORTA |= (c >> 4);
	LCD_STROBE;

	PORTA &= 0xF0 ;
	PORTA |= (c & 0x0F);
	LCD_STROBE;

	DelayUs(50);
}

/*--------------------------------------------------------------------*/
/* 	Clear and home the LCD */

void lcd_clear(void)
{
	LCD_RS = 0;
	lcd_write(0x1);
	DelayMs(2);
}

/*--------------------------------------------------------------------*/
/* ecrit le contenu du buffer dans le LCD en partant de la position pos */

void lcd_putbuf( unsigned char pos)
{
unsigned char c,i ;

   i=0 ;
   lcd_goto(pos) ;

	while( (c=LCD_BUF[i]) != 0 )
      {

      /*if( pos > 15)      lcd_goto((0x40-16)+pos) ;*/

      LCD_RS = 1;	// write characters
      lcd_write(c);
      i++ ;
      /*pos++ ;*/
      }
}

/*--------------------------------------------------------------------*/
/* write one character to the LCD */

void lcd_putch( unsigned char c)
{
	LCD_RS = 1;	// write characters

	PORTA &= 0xF0 ;
	PORTA |= (c >> 4);
	LCD_STROBE;

	PORTA &= 0xF0 ;
	PORTA |= (c & 0x0F);
	LCD_STROBE;

	DelayUs(50);
}


/*--------------------------------------------------------------------*/
/* Go to the specified position */

void lcd_goto(unsigned char pos)
{
	LCD_RS = 0;
	lcd_write(0x80+pos);
}

/*--------------------------------------------------------------------*/
/* initialise the LCD - put into 4 bit mode */

void lcd_init(void)
{
	LCD_RS = 0;	// write control bytes
	DelayMs(15);	// power on delay
	PORTA = 0x3;	// attention!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	LCD_STROBE;
	DelayMs(5);
	LCD_STROBE;
	DelayUs(100);
	LCD_STROBE;
	DelayMs(5);
	PORTA = 0x2;	// set 4 bit mode  // attention!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	LCD_STROBE;
	DelayUs(40);
	lcd_write(0x28);	// 4 bit mode, 1/16 duty, 2 lignes , 5x8 font
	lcd_write(0x08);	// display off
	lcd_write(0x0C);	// display on, blink cursoff
	lcd_write(0x06);	// entry mode
}

/*--------------------------------------------------------------------*/
/* ecrit un caractere non signe en base 10 avec 3 digits dans la      */
/* chaine pointe ( on termine la chaine par un 0                      */
/* si virgule=0 , pas de virgule 1=x,xx 2=xx,x                        */
void lcd_print_uchar(unsigned char data , char *ptr , unsigned char virgule )
{
unsigned char tmp ;

tmp=data/100 ;		// calcul centaines
*ptr++=tmp+'0' ;
data-=tmp*100 ;

if(virgule==1) *ptr++=',' ;

tmp=data/10 ;		// calcul dizaines
*ptr++=tmp+'0' ;
data-=tmp*10 ;

if(virgule==2) *ptr++=',' ;

*ptr++=data+'0' ;	// calcul unites

*ptr=0 ;	// fin de chaine
}


/*--------------------------------------------------------------------*/
/* lecture de la voie du convertisseur ADC0838 */
/* 0 <= voie <= 7 */
unsigned char lit_can( unsigned char voie )
{
unsigned char i,v ;


/* selection du convertisseur ( CS=0 ) */
ADC_CK=0 ;
ADC_CS=0 ;
voie*=8 ; /* decalage ï¿½gauche de trois bits*/
voie|=0xC0 ;	/* preparation du mot pour decalage */

/* envoi des 5 bits de commande + 6eme top / depart conversion */
for( i=0 ; i<6 ; i++ )
	{
	if((voie & 0x80)==0x80)
		ADC_DI=1 ;
	else
		ADC_DI=0 ;

	ADC_CK=1 ;	/* top horloge + */

	voie*=2 ;	/* decalage a gauche */

   #asm			/* delai pour largeur min horloge */
     nop
	  nop
   #endasm

	ADC_CK=0 ;	/* top horloge - */
	}


/* recupere les 8 bits / MSB en premier */
for( i=0 ; i<8 ; i++ )
	{
   v*=2 ;   /* decalage a gauche */

	#asm			/* delai stabilisation sortie */
	  nop
	#endasm
	ADC_CK=1 ;	/* top horloge + */

	if( ADC_DO == 1 )		v+=1 ;

	#asm			/* delai stabilisation sortie */
	  nop
	#endasm

	ADC_CK=0 ;	/* top horloge - */

	}

   /* DEselection du convertisseur ( CS=1 ) */
   ADC_CS =1 ;

return(v) ;

}

/*--------------------------------------------------------------------*/
/* lecture des 4 poussoirs du joystick */
unsigned char lit_bp( void )
{
unsigned char bp ;

bp=0 ;

/* selection du MUX 4052 ( CS=1) */
ADC_CS = 1 ;

BP_MUXA=0 ; /* selection bouton 0 */
BP_MUXB=0 ;

if( BP_STATE != 0 ) bp|=1 ;

BP_MUXA=1 ; /* selection bouton 1 */

if( BP_STATE != 0 ) bp|=2 ;

BP_MUXA=0 ; /* selection bouton 2 */
BP_MUXB=1 ;

if( BP_STATE != 0 ) bp|=4 ;

BP_MUXA=1 ; /* selection bouton 3 */

if( BP_STATE != 0 ) bp|=8 ;

return(~bp) ;
}



/*--------------------------------------------------------------------*/
/* renvoi vrai si le BP designe par bp a ete actionne depuis le dernier appel */
unsigned char bp_set(unsigned char bp )
{
ETAT_BP=lit_bp() ;

// le BP est il à 1 ?
if( (ETAT_BP & bp) == bp )
   {
   // oui! , etait il a 0 ?
   if( (ETAT_BP_PRECED & bp) == 0 )
      {
      //oui , il a donc bien ete actionne
      // on passe l'etat precedent du BP concerne a 1 pour ne plus le detecter
      ETAT_BP_PRECED |= bp ;
      return(VRAI) ;
      }
   }
else  // le BP est a 0
   {
   // on met a jour etat precedent a 0 pour detecter le prochain passage a 1
   ETAT_BP_PRECED &= ~bp ;
   }

return(FAUX) ;
}

/*--------------------------------------------------------------------*/
// controle et tronque le min / max pour le calcul des consignes moteurs
unsigned char calcul_mot( signed int16 tmp)
{
if( tmp > (signed int16)(MAX_MANCHE) )   tmp=(signed int16)(MAX_MANCHE) ;
if( tmp < -((signed int16)(MAX_MANCHE))) tmp=-((signed int16)(MAX_MANCHE)) ;
return((unsigned char)(((signed int16)(P_NEUTRE))+tmp) );
}


/*--------------------------------------------------------------------*/
// renvoi un symbole correspondant a la tendance du moteur concerne
unsigned char tendance(unsigned char m)
{
if( m==P_NEUTRE)  return('0') ;
if( m<P_NEUTRE)   return('-') ;
return('+') ;
}

/*--------------------------------------------------------------------*/
void main(void)
{
unsigned char z ;

/* init E/S ************/
TRISA = 0xA0 ;
TRISB = 0x02 ;

PORTA = 0x00 ;
PORTB = 0x80 ;  /* le bit 7 du PORTB passe a "1" ;  test Bip sonore */

CMCON = 0x07 ;	/* devalide comparateur sur port A */


/* init timer 1 , prediviseur a 8 , Fosc = 4MHz => 1 Top timer = 8uS */
T1CON=0x30 ;

RAZDOG ;

INIT_SERIE() ;

INTCON=0xC0 ;  // valide IT generales , periphs

// INIT DES VARIABLES
MOT_D=P_NEUTRE ;
MOT_G=P_NEUTRE ;
MOT_V=P_NEUTRE ;
IO_UCVIDEO=0 ;	// phares OFF et source video 0
ETAT_UCVIDEO = 0;/* pas de voie d'eau */

PHARES=0 ;
CAMERA=0 ;

ETAT_BP_PRECED=0 ;
ETAT_BP=0 ;

FLAG_ALARME=FAUX ;
FLAG_ACQUIT=FAUX ;

/* intit de l'afficheur LCD */
lcd_init() ;
delay_ms(100) ;
lcd_clear() ;
delay_ms(100) ;

/* affichage du message de presentation ; passage du bit du PORTB 7 ï¿½1; arret du test sonore */
sprintf(LCD_BUF,"  PicSurf V1.0  ") ;
PORTB&=~0x80 ;    // arret alarme sonore
delay_ms( 1000 );
lcd_putbuf(0) ;
delay_ms(1000);
lcd_clear() ;


// etalonnage des manches
NEUTRE_X=127 ;
NEUTRE_Y=127 ;
NEUTRE_Z=127 ;


/* boucle d'affichage des valeurs manches pour reglage neutre */
do {
   MANCHE_X=lit_can(0) ;
   MANCHE_Y=lit_can(4) ;
   MANCHE_Z=lit_can(1) ;

   lcd_print_uchar(MANCHE_X , &LCD_BUF[1] ,0) ;
   LCD_BUF[0]='X' ;
   lcd_putbuf(LCD_L0) ;
   lcd_print_uchar(MANCHE_Y , &LCD_BUF[1] ,0) ;
   LCD_BUF[0]='Y' ;
   lcd_putbuf(LCD_L0+5) ;
   lcd_print_uchar(MANCHE_Z , &LCD_BUF[1] ,0) ;
   LCD_BUF[0]='Z' ;
   lcd_putbuf(LCD_L0+10) ;
   }
 while( lit_bp() & BP_VALID ) ;

lcd_clear() ;

// affichage legende
sprintf(LCD_BUF,"Ph  Us   Uf  GVD") ;
lcd_putbuf(LCD_L0) ;

while(1)
   {

   /*
   for( z=0 ; z<4 ; z++ )
   	{
     	lcd_print_uchar(lit_can(z) , &LCD_BUF[0] ,0) ;
      LCD_BUF[3]=' ' ; LCD_BUF[4]=0 ;
   	lcd_putbuf(4*z) ;
   	delay_ms( 50);
   	}

   for( z=0 ; z<4 ; z++ )
   	{
     	lcd_print_uchar(lit_can(4+z) , &LCD_BUF[0] ,0) ;
      LCD_BUF[3]=' ' ; LCD_BUF[4]=0 ;
   	lcd_putbuf(LCD_L1+(4*z)) ;
   	delay_ms( 50);
   	}

*/
	RAZDOG ;


	// preparation et emission commande UC VIDEO
	PREPARE_CDE_UCVIDEO() ;
	LANCE_TX(TAILLE_CDE_UCVIDEO) ;

	// lecture des voies du convertisseur
	VBAT_SURF=lit_can(7) ;
	VBAT_FOND=lit_can(3) ;   
   MANCHE_X =lit_can(0) ;
   MANCHE_Y =lit_can(4) ;
   MANCHE_Z =lit_can(1) ;

   // lecture des poussoirs et action sur camera et phares
   /*
   NON utilise dans cette version
   if( bp_set(BP_CAMERA) == VRAI )
      {
      CAMERA++ ;
      if( CAMERA >= NB_CAMERAS )  CAMERA=0 ;
      }
   */

   if( bp_set(BP_SPOT) == VRAI )
      {
      PHARES++ ;
      if( PHARES>3) PHARES=0 ;

      // affichage
  	   lcd_goto(LCD_L1) ;
      if( PHARES&1)
       	lcd_putch('1') ;
      else
       	lcd_putch(' ') ;

      if( PHARES&2)
       	lcd_putch('2') ;
      else
       	lcd_putch(' ') ;

      }

   if( bp_set(BP_ACQUIT) == VRAI )
      {
      FLAG_ACQUIT=VRAI ;
      }



	// calcul des commandes des moteurs

   /* moteur VERTICAL */
   /* traitement avec calcul base sur position du neutre*/
   if( MANCHE_Z < NEUTRE_Z )
      {
      MANCHE_Z=NEUTRE_Z-MANCHE_Z ;
      MANCHE_Z/=4 ;
      MOT_V=P_NEUTRE-MANCHE_Z ;
      if( MOT_V < P_MIN ) MOT_V=P_MIN ;
      }
   else
      {
      MANCHE_Z-=NEUTRE_Z ;
      MANCHE_Z/=4 ;
      MOT_V=P_NEUTRE+MANCHE_Z ;
      if( MOT_V > P_MAX ) MOT_V=P_MAX ;
      }

	/* traitement avec neutre fixe = 128 */
	/*if( MANCHE_Z & 0x80 )
		{
		MANCHE_Z &= 0x7F ;
		MANCHE_Z /= 4 ;
		MOT_V=MANCHE_Z ;
		}
   	else
		{
		MANCHE_Z =~ MANCHE_Z ;
		MANCHE_Z &= 0x7F ;
		MANCHE_Z /= 4 ;
		MOT_V=MANCHE_Z ;
		}
*/

   // calcul manche X et Y pour moteurs D et G
   // la variation des valeurs manche est de +-32 autour du neutre
   X=((signed int16)(MANCHE_X)) - ((signed int16)(NEUTRE_X)) ;
   Y=((signed int16)(MANCHE_Y)) - ((signed int16)(NEUTRE_Y)) ;

   // moteur G
   T=Y+X ;
   MOT_G=calcul_mot( T )   ;
   // moteur D
   T=Y-X;
   MOT_D=calcul_mot( T )   ;


// affichage vitesses moteurs pour essais
lcd_print_uchar(MOT_G, &LCD_BUF[0] ,0) ;
lcd_putbuf(LCD_L2) ;
lcd_print_uchar(MOT_V, &LCD_BUF[0] ,0) ;
lcd_putbuf(LCD_L2+7) ;
lcd_print_uchar(MOT_D, &LCD_BUF[0] ,0) ;
lcd_putbuf(LCD_L2+13) ;



	// affichages

	// qualite transmission
   /*
   non affiche
  	lcd_print_uchar(QUALITE_TRANS , &LCD_BUF[0] ,0) ;
	lcd_putbuf(LCD_L1+12) ;
   */

	// tension batterie surface et fond
  	lcd_print_uchar(VBAT_SURF , &LCD_BUF[0] ,2) ;
	lcd_putbuf(LCD_L1+3) ;
  	lcd_print_uchar(VBAT_FOND , &LCD_BUF[0] ,2) ;
	lcd_putbuf(LCD_L1+8) ;

	// tendances moteurs
   lcd_goto(LCD_L1+13) ;
   lcd_putch(tendance(MOT_G)) ;   
   lcd_putch(tendance(MOT_V)) ;
   lcd_putch(tendance(MOT_D)) ;   


	// gestion des alarmes
	if(QUALITE_TRANS < 50)	// transmission
		{
   	sprintf(LCD_BUF,"Alarme LIAISON ") ;
		lcd_putbuf(LCD_L3) ;
      FLAG_ALARME=VRAI ;
		}
	else if( (ETAT_UCVIDEO&0x0F) != 0 )	// voie d'eau
		{
		sprintf(LCD_BUF,"Alarme EAU     ") ;
		lcd_putbuf(LCD_L3) ;
      FLAG_ALARME=VRAI ;
		}

	else if( VBAT_SURF < VSURF_MIN )	// tension batterie surface
		{
		sprintf(LCD_BUF,"Alarme bat SURF") ;
		lcd_putbuf(LCD_L3) ;
      FLAG_ALARME=VRAI ;
		}

	else if( VBAT_FOND < VFOND_MIN )	// tension batterie fond
		{
		sprintf(LCD_BUF,"Alarme bat FOND") ;
		lcd_putbuf(LCD_L3) ;
      FLAG_ALARME=VRAI ;
		}

	else
		{
		// affichage pas d'alarmes en cours
		sprintf(LCD_BUF," pas d'alarmes ") ;
		lcd_putbuf(LCD_L3) ;
      FLAG_ALARME=FAUX ;
      FLAG_ACQUIT=FAUX ;
		}


   // gestion du buzzer
   if( (FLAG_ALARME==VRAI) && (FLAG_ACQUIT==FAUX) )
      BUZZER=1 ;
   else
      BUZZER=0 ;


	delay_ms(30);

   } ;

}






