Import initial du projet shipheart_appli
This commit is contained in:
+548
@@ -0,0 +1,548 @@
|
||||
//**********************************************************************************************************************************************************************************
|
||||
// Fichier C_BUS.C
|
||||
//
|
||||
// Contient toutes les fonctions liées à la gestion du C_Bus
|
||||
//**********************************************************************************************************************************************************************************/
|
||||
|
||||
|
||||
#define __DEBUG_C_BUS 0 // Passer cette ligne à 0: aucun message de debug de C_bus, 1: les messages de debug de C_Bus sur l'écran, 2: sur fichier (cf NOM_FICHIER_DEBUG_BUS dans 'debug.h') ou 3: sur l'écran et fichier.
|
||||
|
||||
// Includes :
|
||||
#include "main.h"
|
||||
|
||||
// Prototypes :
|
||||
int8_t init_c_bus(void);
|
||||
void gestion_c_bus(void);
|
||||
int8_t gestion_protocole_rx_c_bus(void);
|
||||
void gestion_protocole_tx_c_bus(void);
|
||||
int8_t c_bus_next_write_buffer_cdes(uint8_t priorite);
|
||||
|
||||
// Variables globales :
|
||||
struct Struct_c_bus c_bus;
|
||||
|
||||
|
||||
/**********************************************************************************************************************************************************************************
|
||||
Fonction INIT_C_BUS
|
||||
|
||||
Fonction d'initialisation du C-Bus
|
||||
**********************************************************************************************************************************************************************************/
|
||||
int8_t init_c_bus(void)
|
||||
{
|
||||
//------------------------------------------------------------------------------------------------------
|
||||
// Init des variables générales :
|
||||
|
||||
c_bus.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_INIT;
|
||||
c_bus.sequenceur.compteur = C_BUS_TEMPO_INIT;
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_INIT;
|
||||
c_bus.protocole_rx.sequenceur.compteur = C_BUS_PROTOCOLE_RX_TEMPO_INIT;
|
||||
c_bus.protocole_rx.flag_dle = FALSE;
|
||||
|
||||
c_bus.protocole_tx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_TX_INIT;
|
||||
c_bus.protocole_tx.sequenceur.compteur = C_BUS_PROTOCOLE_TX_TEMPO_INIT;
|
||||
|
||||
|
||||
|
||||
// Affichage du message de débug :
|
||||
affichage_debug(__FILE__, __LINE__, "Initialisation du C-BUS\t\t: OK", TYPE_MESSAGE_DEBUG_OK);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************************************************************************************************************************
|
||||
Fonction GESTION_C_BUS
|
||||
|
||||
Fonction de plus haut niveau de gestion du C-Bus
|
||||
**********************************************************************************************************************************************************************************/
|
||||
void gestion_c_bus(void)
|
||||
{
|
||||
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
|
||||
|
||||
|
||||
switch(c_bus.sequenceur.etat)
|
||||
{
|
||||
//--------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_C_BUS_INIT :
|
||||
{
|
||||
if (c_bus.sequenceur.compteur == 0)
|
||||
{
|
||||
//.........................................................
|
||||
// Vidage du buffer de réception de tous les caractères reçus pendant la phase d'init :
|
||||
serial1.ptr_debut_buffer_rx = 0;
|
||||
serial1.ptr_fin_buffer_rx = 0;
|
||||
|
||||
//.........................................................
|
||||
// Mise à jour des séquenceurs pour démarrage des envois :
|
||||
c_bus.protocole_rx.sequenceur.compteur = 0;
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_REPOS;
|
||||
c_bus.protocole_tx.sequenceur.compteur = 0;
|
||||
c_bus.protocole_tx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_TX_REPOS;
|
||||
c_bus.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_REPOS;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_C_BUS_REPOS :
|
||||
{
|
||||
//=================================
|
||||
// Gestion du C-Bus en émission :
|
||||
|
||||
gestion_protocole_tx_c_bus(); // Vérifie si une réponse (Up) ou une commande (Down) est en attente. Si oui, elle la traite et l'émet.
|
||||
|
||||
|
||||
//=================================
|
||||
// Gestion du C-Bus en réception :
|
||||
|
||||
if (gestion_protocole_rx_c_bus() == 1) // Vérifie si une commande (Up) ou une réponse (Down) a été reçue.
|
||||
{
|
||||
|
||||
#ifdef __DEBUG_C_BUS
|
||||
c_bus.down.reponse.reponse[c_bus.down.reponse.lg_reponse] = 0; // On ajoute un /0 à la fin mais on ne change surtout pas la longueur qui est utilisée pour les transferts binaires.
|
||||
affichage_debug_bus(TYPE_BUS_DEBUG_C_BUS, "Rx", (char *) c_bus.down.reponse.reponse, __DEBUG_C_BUS);
|
||||
#endif
|
||||
if (c_bus.protocole_rx.sens == 'U') // Réception d'une commande (Up) :
|
||||
{
|
||||
c_bus_up_recherche_commande(); // Recherche et traitement de la commande reçue. La réponse est préparée et son 'flag_ready' est positionné afin d'être traité par gestion_protocole_tx_c_bus() lors de la prochaine boucle.
|
||||
}
|
||||
else // Réception d'une réponse (Down) :
|
||||
{
|
||||
if (c_bus_down_recherche_reponse() != -1) // Comme la réponse a été reçue sans erreur, on libère le Protocole_Tx :
|
||||
{
|
||||
c_bus.down.flag_attente_reponse = FALSE;
|
||||
c_bus.protocole_tx.repetitions = 0;
|
||||
c_bus.protocole_tx.sequenceur.compteur_time_out = 0;
|
||||
}
|
||||
else c_bus.protocole_tx.sequenceur.compteur_time_out = 0; // En cas de réponse reçue avec erreur, on simule un déclenchement de time-out pour faire de suite le test du nombre de répétitions (cela permet juste de ne pas attandre l'expiration du time-out)
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------
|
||||
default :
|
||||
{
|
||||
sprintf(tmp, "L'état du séquenceur C_bus est inconnu [%i]. Il est repositionné au REPOS", c_bus.sequenceur.etat);
|
||||
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
|
||||
c_bus.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_REPOS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************************************************************************************
|
||||
Fonction : Appelée en tâche de fond, cette fonction lit le buffer de réception de l'UART 1 et traite les trames reçues.
|
||||
Soit une commande du Compagnon (Up), soit une réponse à une commande du CM3+ (Down)
|
||||
Reçoit : Rien
|
||||
Renvoit : 0 si RAS, 1 si une nouvelle commande complète a été reçue
|
||||
******************************************************************************************************************************************************************/
|
||||
int8_t gestion_protocole_rx_c_bus(void)
|
||||
{
|
||||
uint8_t c;
|
||||
bool flag_controle;
|
||||
bool flag_cde_recue;
|
||||
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
|
||||
|
||||
|
||||
flag_cde_recue = FALSE;
|
||||
|
||||
// Traitement de chaque caractère reçu :
|
||||
while (serial1.ptr_debut_buffer_rx != serial1.ptr_fin_buffer_rx)
|
||||
{
|
||||
// Calcul de la prochaine position à lire (avec bouclage en fin de buffer tournant) :
|
||||
if (++ serial1.ptr_debut_buffer_rx == MAX_TAILLE_RX_BUFFER_UART) serial1.ptr_debut_buffer_rx = 0;
|
||||
|
||||
// Lecture du caractère dans le buffer :
|
||||
flag_controle = FALSE; // Permettra de marquer le caractère en cours de lecture
|
||||
c = serial1.buffer_rx[serial1.ptr_debut_buffer_rx]; // Lecture du caractère à traiter
|
||||
|
||||
|
||||
// Traitement des caractères DLE :
|
||||
if (c_bus.protocole_rx.flag_dle == TRUE) // Si le caractère précédent était un DLE
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case ASCII_DLE : break; // C'est un DLE qui a fort justement été doublé, on va donc traiter le second comme un octet de data.
|
||||
|
||||
case ASCII_SOH : // Caractères de contrôle échappés
|
||||
case ASCII_STX :
|
||||
case ASCII_ETX :
|
||||
{
|
||||
flag_controle = TRUE; // On marque donc 'x' comme un caractère de contrôle et non une data
|
||||
break;
|
||||
}
|
||||
|
||||
default: // erreur de "DLE isolé"
|
||||
{
|
||||
flag_controle = TRUE; // On marque donc 'x' comme un caractère de contrôle et non une data
|
||||
c = ASCII_NULL; // On change volontairement la valeur à NULL afin que la trame soit rejetée et qu'en fonction de l'état du séquenceur, un NACK soit retourné ou non...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
c_bus.protocole_rx.flag_dle = FALSE; // Dans tous les cas précédent, le premier DLE a été traité (y compris dans le cas d'un double DLE)
|
||||
}
|
||||
else // Si le caractère précédent n'était PAS un DLE :
|
||||
{
|
||||
if (c == ASCII_DLE) c_bus.protocole_rx.flag_dle = TRUE; // On positionne le flag si c'est un DLE
|
||||
}
|
||||
|
||||
|
||||
// Traitement du caractère reçu :
|
||||
if (c_bus.protocole_rx.flag_dle == FALSE) // Sauf si on est sur le "premier" DLE...
|
||||
{
|
||||
switch(c_bus.protocole_rx.sequenceur.etat)
|
||||
{
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_INIT :
|
||||
{
|
||||
// NB : Le caractère lu est jeté tant que la phase d'init n'est pas terminée...
|
||||
// NB 2 : le passage à l'état REPOS se fait par le séquenceur C-Bus, indépendemment de la réception ou non de caractères.
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_REPOS :
|
||||
{
|
||||
if ((flag_controle == TRUE) && (c == ASCII_SOH)) // Attente de réception du SOH de début de trame
|
||||
{
|
||||
c_bus.protocole_rx.cs = (uint16_t) c; // Premier chargement du CS
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_SENS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_SENS :
|
||||
{
|
||||
c_bus.protocole_rx.cs += (uint16_t) c; // Rechargement du CS
|
||||
|
||||
if ((c == 'D') || (c =='U'))
|
||||
{
|
||||
c_bus.protocole_rx.sens = c;
|
||||
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_STX;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __DEBUG_C_BUS
|
||||
affichage_debug(__FILE__, __LINE__, "Etat séquenceur C-Bus = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_SENS", TYPE_MESSAGE_DEBUG_WARNING);
|
||||
#endif
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_ERREUR; // Erreur de CS
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_STX :
|
||||
{
|
||||
c_bus.protocole_rx.cs += (uint16_t) c; // Rechargement du CS
|
||||
|
||||
if ((flag_controle == TRUE) && (c == ASCII_STX))
|
||||
{
|
||||
if (c_bus.protocole_rx.sens == 'U') c_bus.up.cde.lg_cde = 0; // On reçoit une commande Up...
|
||||
else c_bus.down.reponse.lg_reponse = 0; // ... ou une réponse à une commande Down
|
||||
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_DATA;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __DEBUG_C_BUS
|
||||
affichage_debug(__FILE__, __LINE__, "Etat séquenceur C-Bus = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_STX", TYPE_MESSAGE_DEBUG_WARNING);
|
||||
#endif
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_ERREUR; // Erreur de CS
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_DATA :
|
||||
{
|
||||
c_bus.protocole_rx.cs += (uint16_t) c; // Rechargement du CS
|
||||
|
||||
if (flag_controle == FALSE)
|
||||
{
|
||||
if (c_bus.protocole_rx.sens == 'U') c_bus.up.cde.cde[c_bus.up.cde.lg_cde ++] = c;
|
||||
else c_bus.down.reponse.reponse[c_bus.down.reponse.lg_reponse ++] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c == ASCII_ETX)
|
||||
{
|
||||
c_bus.protocole_rx.cs_recu = 0;
|
||||
c_bus.protocole_rx.ptr_cs_recu = 0;
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_CS;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __DEBUG_C_BUS
|
||||
affichage_debug(__FILE__, __LINE__, "Etat séquenceur C-Bus = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_DATA", TYPE_MESSAGE_DEBUG_WARNING);
|
||||
#endif
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_ERREUR; // Erreur de CS
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_CS :
|
||||
{
|
||||
if (c_bus.protocole_rx.ptr_cs_recu == 0) // Premier caractère de CS reçu, à archviver en LSB :
|
||||
{
|
||||
c_bus.protocole_rx.cs_recu = ((uint16_t) c) & 0x00FF;
|
||||
c_bus.protocole_rx.ptr_cs_recu ++;
|
||||
}
|
||||
else // Second caractère de CS reçu, à archiver en MSB puis comparer avec la valeur calculée :
|
||||
{
|
||||
c_bus.protocole_rx.cs_recu |= (((uint16_t) c) & 0x00FF) << 8;
|
||||
if (c_bus.protocole_rx.cs == c_bus.protocole_rx.cs_recu)
|
||||
{
|
||||
flag_cde_recue = TRUE; // Flag pour remonter qu'une commande a été reçue et sans erreur
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_REPOS; // Retour du séquenceur au repos
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __DEBUG_C_BUS
|
||||
affichage_debug(__FILE__, __LINE__, "Etat séquenceur C-Bus = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_CS", TYPE_MESSAGE_DEBUG_WARNING);
|
||||
#endif
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_ERREUR; // Erreur de CS
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_ERREUR :
|
||||
{
|
||||
|
||||
// !!!! Voir si retour d'un NACK.... !!!!
|
||||
|
||||
affichage_debug(__FILE__, __LINE__, "Erreur de protocole Rx sur C-Bus", TYPE_MESSAGE_DEBUG_ERREUR);
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_REPOS;
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
default :
|
||||
{
|
||||
sprintf(tmp, "L'état du séquenceur C-Bus.Protocole_Rx est inconnu [%i]. Il est repositionné au REPOS", c_bus.protocole_rx.sequenceur.etat);
|
||||
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
|
||||
c_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_RX_REPOS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flag_cde_recue) break;
|
||||
|
||||
}
|
||||
|
||||
if (flag_cde_recue) return(1);
|
||||
else return(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************************************************************************************
|
||||
Fonction : Appelée en tâche de fond, cette fonction vérifie si une réponse est à émettre vers le Compagnon (Up) ou si une commande est prête à être émise
|
||||
dans le buffer de commandes Down. Si oui, elle gère via son séquenceur le formattage de la trame à émettre.
|
||||
Reçoit : Rien
|
||||
Renvoit : Rien
|
||||
*****************************************************************************************************************************************************************/
|
||||
void gestion_protocole_tx_c_bus(void)
|
||||
{
|
||||
uint16_t i;
|
||||
uint8_t c;
|
||||
uint8_t sens;
|
||||
uint16_t cs;
|
||||
uint8_t tx_buffer[C_BUS_MAX_TAILLE_BUFFER_TX];
|
||||
uint16_t lg_tx_buffer;
|
||||
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
|
||||
|
||||
|
||||
switch(c_bus.protocole_tx.sequenceur.etat)
|
||||
{
|
||||
//--------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_TX_INIT :
|
||||
{
|
||||
// NB : le passage à l'état REPOS se fait par le séquenceur C-Bus, indépendemment de la présence de commande à émettre
|
||||
break;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_TX_REPOS :
|
||||
{
|
||||
//..................................
|
||||
// Recherche d'une trame à émettre :
|
||||
if (c_bus.up.reponse.flag_ready) // Si une réponse est à émettre (en mode Up donc), elle est émise en priorité :
|
||||
{
|
||||
c_bus.up.reponse.flag_ready = FALSE; // RAZ du flag
|
||||
sens = 'U'; // Mise à jour du sens avant préparation de la trame et envoi
|
||||
}
|
||||
else // Sinon, on regarde si une action est à faire en mode Down :
|
||||
{
|
||||
sens = 'D'; // Pour ne pas l'oublier....
|
||||
|
||||
if (c_bus.down.flag_attente_reponse) // Cas où une commande Down a déjà été émise et qu'on est en attente de réponse :
|
||||
{
|
||||
if (c_bus.protocole_tx.sequenceur.compteur_time_out == 0) // On vérifie alors si le time-out a expiré :
|
||||
{
|
||||
c_bus.down.flag_attente_reponse = FALSE; // RAZ du flag (qui sera éventuellement remis à 1 si la répétition a lieu)
|
||||
c_bus.protocole_tx.repetitions ++; // Incrémentation du nombre de répétitions
|
||||
if (c_bus.protocole_tx.repetitions > C_BUS_PROTOCOLE_TX_MAX_REPETITIONS) // Si le nombre maxi de répétitions a été dépassé, on laisse tomber la commande
|
||||
{
|
||||
c_bus.protocole_tx.repetitions = 0; // RAZ du compteur pour utilisation ultérieure
|
||||
break; // Sortie du séquenceur
|
||||
}
|
||||
}
|
||||
else break; // Tant qu'on est en attente d'une réponse et que le time-out n'est pas expiré, on ne traite aucun envoi en mode Down
|
||||
}
|
||||
else // Sinon, recherche d'une nouvelle commande à émettre en mode Down :
|
||||
{
|
||||
if (c_bus.down.ptr_debut_buffer_cdes != c_bus.down.ptr_fin_buffer_cdes) // Cas où il y a une commande en attente d'émission...
|
||||
{
|
||||
// ATTENTION : gérer les priorités ...!
|
||||
|
||||
if (++ c_bus.down.ptr_debut_buffer_cdes == C_BUS_MAX_TAILLE_BUFFER_CDES) c_bus.down.ptr_debut_buffer_cdes = 0;
|
||||
#ifdef __DEBUG_C_BUS
|
||||
c_bus.down.buffer_cdes[c_bus.down.ptr_debut_buffer_cdes].cde[c_bus.down.buffer_cdes[c_bus.down.ptr_debut_buffer_cdes].lg_cde] = 0; // On ajoute un /0 à la fin mais on ne change surtout pas la longueur qui est utilisée pour les transferts binaires.
|
||||
affichage_debug_bus(TYPE_BUS_DEBUG_C_BUS, "Tx", (char *) c_bus.down.buffer_cdes[c_bus.down.ptr_debut_buffer_cdes].cde, __DEBUG_C_BUS);
|
||||
#endif
|
||||
}
|
||||
else break; // Il n'y a pas de nouvelle commande en attente d'émission
|
||||
}
|
||||
}
|
||||
|
||||
//.....................................
|
||||
// Préparation de la trame d'émission :
|
||||
lg_tx_buffer = 0;
|
||||
|
||||
tx_buffer[lg_tx_buffer ++] = ASCII_DLE;
|
||||
tx_buffer[lg_tx_buffer ++] = ASCII_SOH;
|
||||
cs = ASCII_SOH; // Initialisation du CS calculé
|
||||
tx_buffer[lg_tx_buffer ++] = sens;
|
||||
cs += sens; // Rechargement du CS
|
||||
tx_buffer[lg_tx_buffer ++] = ASCII_DLE;
|
||||
tx_buffer[lg_tx_buffer ++] = ASCII_STX;
|
||||
cs += ASCII_STX; // Rechargement du CS
|
||||
|
||||
if (sens == 'D')
|
||||
{
|
||||
for (i=0; (i < c_bus.down.buffer_cdes[c_bus.down.ptr_debut_buffer_cdes].lg_cde) && (lg_tx_buffer < C_BUS_MAX_TAILLE_BUFFER_TX); i++)
|
||||
{
|
||||
c = c_bus.down.buffer_cdes[c_bus.down.ptr_debut_buffer_cdes].cde[i];
|
||||
if (c == ASCII_DLE) tx_buffer[lg_tx_buffer ++] = ASCII_DLE;
|
||||
tx_buffer[lg_tx_buffer ++] = c;
|
||||
cs += c; // Rechargement du CS
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; (i < c_bus.up.reponse.lg_reponse) && (lg_tx_buffer < C_BUS_MAX_TAILLE_BUFFER_TX); i++)
|
||||
{
|
||||
c = c_bus.up.reponse.reponse[i];
|
||||
if (c == ASCII_DLE) tx_buffer[lg_tx_buffer ++] = ASCII_DLE;
|
||||
tx_buffer[lg_tx_buffer ++] = c;
|
||||
cs += c; // Rechargement du CS
|
||||
}
|
||||
}
|
||||
|
||||
tx_buffer[lg_tx_buffer ++] = ASCII_DLE;
|
||||
tx_buffer[lg_tx_buffer ++] = ASCII_ETX;
|
||||
cs += ASCII_ETX; // Rechargement du CS
|
||||
|
||||
c = (uint8_t)(cs & 0x00FF); // LSB du CS
|
||||
if (c == ASCII_DLE) tx_buffer[lg_tx_buffer ++] = ASCII_DLE;
|
||||
tx_buffer[lg_tx_buffer ++] = c;
|
||||
|
||||
c = (uint8_t)(cs >> 8); // MSB du CS
|
||||
if (c == ASCII_DLE) tx_buffer[lg_tx_buffer ++] = ASCII_DLE;
|
||||
tx_buffer[lg_tx_buffer ++] = c;
|
||||
|
||||
//.............................
|
||||
// Envoi au driver d'émission :
|
||||
write(config_serial1.filestream, tx_buffer, lg_tx_buffer);
|
||||
|
||||
//..........................................................
|
||||
// Mise à jour des paramètres après l'émission de la trame :
|
||||
if (sens == 'D') // S'il s'agissait d'une commande émise en mode Down, on lance un time-out et on indique qu'on attend la réponse :
|
||||
{
|
||||
c_bus.down.flag_attente_reponse = TRUE;
|
||||
c_bus.protocole_tx.sequenceur.compteur_time_out = C_BUS_TIME_OUT_REPONSE_TX;
|
||||
}
|
||||
else ; // S'il s'agissait d'une réponse à une commande reçue en mode Up, on revient immédiatement au repos (la gestion des répétitions des commandes est de la responsabilité du maitre)
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
default :
|
||||
{
|
||||
sprintf(tmp, "L'état du séquenceur C-Bus.Protocole_Tx est inconnu [%i]. Il est repositionné au REPOS", c_bus.protocole_tx.sequenceur.etat);
|
||||
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
|
||||
c_bus.protocole_tx.sequenceur.etat = ETAT_SEQUENCEUR_C_BUS_PROTOCOLE_TX_REPOS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************************************************************************************
|
||||
Fonction : Incrémente le pointeur du buffer de commandes en attente d'émission vers C-Bus
|
||||
La fonction gère :
|
||||
- le rebouclage en fin de buffer (buffer circulaire)
|
||||
- le dépassement (quand la fin rattrape le début) en émettant un message de debug et en choissant :
|
||||
. soit d'écraser la commande la plus ancienne si elle est de priorité inférieure (strictement)
|
||||
. soit refuser l'ajout en laissant le pointeur de fin du buffer à sa position et en renvoyant une erreur.
|
||||
Reçoit : La priorité de la commande à ajouter (permet d'arbitrer dans la cas où le buffer est plein)
|
||||
Renvoit : 0 si une position disponible a été trouvée, -1 si aucune position n'est disponible.
|
||||
******************************************************************************************************************************************************************/
|
||||
int8_t c_bus_next_write_buffer_cdes(uint8_t priorite)
|
||||
{
|
||||
int8_t retour = 0;
|
||||
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
|
||||
|
||||
// Incrémentation :
|
||||
if (++ c_bus.down.ptr_fin_buffer_cdes == C_BUS_MAX_TAILLE_BUFFER_CDES) c_bus.down.ptr_fin_buffer_cdes = 0;
|
||||
|
||||
// Vérification si buffer plein :
|
||||
if (c_bus.down.ptr_fin_buffer_cdes == c_bus.down.ptr_debut_buffer_cdes)
|
||||
{
|
||||
if (c_bus.down.buffer_cdes[c_bus.down.ptr_fin_buffer_cdes].priorite >= priorite)
|
||||
{
|
||||
// Décrémentation du pointeur puisqu'on ne va pas accepter la nouvelle commande qui n'a pas une priorité suffisante :
|
||||
if (c_bus.down.ptr_fin_buffer_cdes == 0) c_bus.down.ptr_fin_buffer_cdes = (C_BUS_MAX_TAILLE_BUFFER_CDES - 1);
|
||||
else c_bus.down.ptr_fin_buffer_cdes --;
|
||||
|
||||
// Message de débug :
|
||||
sprintf(tmp, "Buffer de commandes C-Bus plein. La demande de stockage d'une nouvelle commande a été rejetée...");
|
||||
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
|
||||
|
||||
// Enregistrement dans l'historique :
|
||||
enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_BUS_BUFFER_COMMANDES_PLEIN, (uint32_t) 'C', 0, NULL);
|
||||
|
||||
retour = -1;
|
||||
}
|
||||
else // Dans ce cas, la nouvelle commande est plus prioritaire (strictement) à la commande existante dans le buffer et elle va la remplacer.
|
||||
{
|
||||
// Message de débug :
|
||||
sprintf(tmp, "Buffer de commandes C-Bus plein. La demande de stockage d'une nouvelle commande a écrasée la commande la plus ancienne qui était de priorité inférieure...");
|
||||
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
return (retour);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user