Import initial du projet shipheart_appli
This commit is contained in:
+415
@@ -0,0 +1,415 @@
|
||||
//**********************************************************************************************************************************************************************************
|
||||
// Fichier M_BUS.C
|
||||
//
|
||||
// Contient toutes les fonctions liées à la gestion du M_Bus (liaison avec le Modem SIM7070G)
|
||||
//**********************************************************************************************************************************************************************************/
|
||||
|
||||
#define __DEBUG_M_BUS 0 // Passer cette ligne à 0: aucun message de debug de M_bus, 1: les messages de debug de M_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_m_bus(void);
|
||||
void gestion_m_bus(void);
|
||||
int8_t gestion_protocole_rx_m_bus(void);
|
||||
void gestion_protocole_tx_m_bus(void);
|
||||
int8_t m_bus_next_write_buffer_cdes(uint8_t priorite);
|
||||
|
||||
// Variables globales :
|
||||
struct Struct_m_bus m_bus;
|
||||
|
||||
|
||||
/**********************************************************************************************************************************************************************************
|
||||
Fonction INIT_M_BUS
|
||||
|
||||
Fonction d'initialisation du C-Bus
|
||||
**********************************************************************************************************************************************************************************/
|
||||
int8_t init_m_bus(void)
|
||||
{
|
||||
|
||||
if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1)
|
||||
{
|
||||
//------------------------------------------------------------------------------------------------------
|
||||
// Init des variables générales :
|
||||
|
||||
m_bus.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_INIT;
|
||||
m_bus.sequenceur.compteur = M_BUS_TEMPO_INIT;
|
||||
|
||||
m_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_INIT;
|
||||
m_bus.protocole_rx.sequenceur.compteur = M_BUS_PROTOCOLE_RX_TEMPO_INIT;
|
||||
|
||||
m_bus.protocole_tx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_TX_INIT;
|
||||
m_bus.protocole_tx.sequenceur.compteur = M_BUS_PROTOCOLE_TX_TEMPO_INIT;
|
||||
|
||||
// Affichage du message de débug :
|
||||
affichage_debug(__FILE__, __LINE__, "Initialisation du M-BUS\t\t: OK", TYPE_MESSAGE_DEBUG_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Affichage du message de débug :
|
||||
affichage_debug(__FILE__, __LINE__, "Initialisation du M-BUS\t\t: Devalidé car non valide sur cette version de ShipBase", TYPE_MESSAGE_DEBUG_WARNING);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************************************************************************************************************************
|
||||
Fonction GESTION_M_BUS
|
||||
|
||||
Fonction de plus haut niveau de gestion du C-Bus
|
||||
**********************************************************************************************************************************************************************************/
|
||||
void gestion_m_bus(void)
|
||||
{
|
||||
int8_t ret;
|
||||
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
|
||||
|
||||
|
||||
if (systeme.generation_shipbase != GENERATION_SHIPBASE_V1) return;
|
||||
|
||||
switch(m_bus.sequenceur.etat)
|
||||
{
|
||||
//--------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_M_BUS_INIT :
|
||||
{
|
||||
if (m_bus.sequenceur.compteur == 0)
|
||||
{
|
||||
//.........................................................
|
||||
// Vidage du buffer de réception de tous les caractères reçus pendant la phase d'init :
|
||||
serial0.ptr_debut_buffer_rx = 0;
|
||||
serial0.ptr_fin_buffer_rx = 0;
|
||||
|
||||
//.........................................................
|
||||
// Vidage du buffer de commandes (utile dans le cas d'un reset du modem pour overflow) :
|
||||
m_bus.down.ptr_debut_buffer_cdes = 0;
|
||||
m_bus.down.ptr_fin_buffer_cdes = 0;
|
||||
|
||||
//.........................................................
|
||||
// Mise à jour des séquenceurs pour démarrage des envois :
|
||||
m_bus.protocole_rx.sequenceur.compteur = 0;
|
||||
m_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_REPOS;
|
||||
m_bus.protocole_tx.sequenceur.compteur = 0;
|
||||
m_bus.protocole_tx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_TX_REPOS;
|
||||
|
||||
m_bus.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_REPOS;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_M_BUS_REPOS :
|
||||
{
|
||||
if (modem.etat == ON) // Si le modem n'est pas ON, il est inutile d'essayer de communiquer avec lui.
|
||||
{
|
||||
//=================================
|
||||
// Gestion du M-Bus en émission :
|
||||
|
||||
gestion_protocole_tx_m_bus(); // Vérifie si une commande (Down) est en attente. Si oui, elle la traite et l'émet.
|
||||
|
||||
|
||||
//=================================
|
||||
// Gestion du M-Bus en réception :
|
||||
|
||||
ret = gestion_protocole_rx_m_bus();
|
||||
if (ret != 0) // Vérifie si une réponse (à une commande Down) a été reçue.
|
||||
{
|
||||
#ifdef __DEBUG_M_BUS
|
||||
m_bus.down.reponse.reponse[m_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.
|
||||
if (ret == 1) affichage_debug_bus(TYPE_BUS_DEBUG_M_BUS, "Rx", (char *) m_bus.down.reponse.reponse, __DEBUG_M_BUS); // Cas d'une réponse normale
|
||||
else
|
||||
{
|
||||
sprintf(tmp, "[%li data bytes]", strlen((const char *)m_bus.down.reponse.reponse));
|
||||
affichage_debug_bus(TYPE_BUS_DEBUG_M_BUS, "Rx", tmp, __DEBUG_M_BUS); // Cas d'une réponse en mode binaire
|
||||
}
|
||||
#endif
|
||||
m_bus_down_analyse_reponse_commande();
|
||||
// Traitement de la réponse à la commande...
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------
|
||||
default :
|
||||
{
|
||||
sprintf(tmp, "L'état du séquenceur M-bus est inconnu [%i]. Il est repositionné au REPOS", m_bus.sequenceur.etat);
|
||||
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
|
||||
m_bus.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_REPOS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************************************************************************************
|
||||
Fonction : Appelée en tâche de fond, cette fonction lit le buffer de réception de l'UART 0 et traite les trames reçues (réponse du modem à une commande du CM3+)
|
||||
Reçoit : Rien
|
||||
Renvoit : 0 si RAS, 1 si une réponse complète a été reçue, 2 si réponse complète en mode binaire a été reçue
|
||||
******************************************************************************************************************************************************************/
|
||||
int8_t gestion_protocole_rx_m_bus(void)
|
||||
{
|
||||
uint8_t c;
|
||||
int8_t reponse_recue;
|
||||
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
|
||||
|
||||
|
||||
reponse_recue = 0;
|
||||
|
||||
// Traitement de chaque caractère reçu :
|
||||
while (serial0.ptr_debut_buffer_rx != serial0.ptr_fin_buffer_rx)
|
||||
{
|
||||
// Calcul de la prochaine position à lire (avec bouclage en fin de buffer tournant) :
|
||||
if (++ serial0.ptr_debut_buffer_rx == MAX_TAILLE_RX_BUFFER_UART) serial0.ptr_debut_buffer_rx = 0;
|
||||
|
||||
// Lecture du caractère dans le buffer :
|
||||
c = serial0.buffer_rx[serial0.ptr_debut_buffer_rx]; // Lecture du caractère à traiter
|
||||
|
||||
// Traitement du caractère reçu :
|
||||
switch(m_bus.protocole_rx.sequenceur.etat)
|
||||
{
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_M_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 M-Bus, indépendemment de la réception ou non de caractères.
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_REPOS :
|
||||
{
|
||||
|
||||
if (c == ASCII_CR) // Attente de réception du CR de début de trame
|
||||
{
|
||||
m_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_ATTENTE_LF;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_ATTENTE_LF :
|
||||
{
|
||||
|
||||
if (c == ASCII_CR) break; // Cas d'un CR qui suit un CR. On reste en attente d'un LF à venir...
|
||||
|
||||
if (c == ASCII_LF)
|
||||
{
|
||||
if (m_bus.down.reponse.lg_reponse != 0) reponse_recue = 1; // Si la longueur actuelle de réponse est nulle, on ne fait rien (on va juste revenir en mode data pour le prochain caractère)
|
||||
|
||||
m_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_DATA; // Dans tous les cas, après un CR/LF, on passe en mode Data car il arrive qu'un CR/LF soit juste un séparateur entre plusieurs blocs (il y a donc une fin mais pas de "début" suivant)
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_REPOS;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_DATA :
|
||||
{
|
||||
|
||||
if (c != ASCII_CR) m_bus.down.reponse.reponse[m_bus.down.reponse.lg_reponse ++] = c;
|
||||
else
|
||||
{
|
||||
m_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_ATTENTE_LF;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_FLUX_BINAIRE:
|
||||
{
|
||||
m_bus.down.reponse.reponse[m_bus.down.reponse.lg_reponse ++] = c;
|
||||
if (m_bus.down.reponse.lg_reponse == m_bus.down.reponse.lg_reponse_attendue)
|
||||
{
|
||||
reponse_recue = 2;
|
||||
m_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_REPOS;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
default :
|
||||
{
|
||||
sprintf(tmp, "L'état du séquenceur M-Bus.Protocole_Rx est inconnu [%i]. Il est repositionné au REPOS", m_bus.protocole_rx.sequenceur.etat);
|
||||
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
|
||||
m_bus.protocole_rx.sequenceur.etat = ETAT_SEQUENCEUR_M_BUS_PROTOCOLE_RX_REPOS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (reponse_recue != 0) break;
|
||||
|
||||
}
|
||||
|
||||
return(reponse_recue);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************************************************************************************
|
||||
Fonction : Appelée en tâche de fond, cette fonction vérifie 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_m_bus(void)
|
||||
{
|
||||
uint16_t i;
|
||||
uint8_t tx_buffer[M_BUS_MAX_TAILLE_BUFFER_TX];
|
||||
uint16_t lg_tx_buffer;
|
||||
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
|
||||
|
||||
|
||||
switch(m_bus.protocole_tx.sequenceur.etat)
|
||||
{
|
||||
//--------------------------------------------------------
|
||||
case ETAT_SEQUENCEUR_M_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_M_BUS_PROTOCOLE_TX_REPOS :
|
||||
{
|
||||
//..................................
|
||||
// Recherche d'une trame à émettre :
|
||||
|
||||
if (m_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 (m_bus.protocole_tx.sequenceur.compteur_time_out == 0) // On vérifie alors si le time-out a expiré :
|
||||
{
|
||||
m_bus.down.flag_attente_reponse = FALSE; // RAZ du flag (qui sera éventuellement remis à 1 si la répétition a lieu)
|
||||
m_bus.protocole_tx.repetitions ++; // Incrémentation du nombre de répétitions
|
||||
if (m_bus.protocole_tx.repetitions > m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].max_repetitions) // Si le nombre maxi de répétitions a été dépassé, on laisse tomber la commande
|
||||
{
|
||||
|
||||
// !!! Il serait peut-être intéressant d'informer la couche supérieure que la commande est abandonnée sans avoir obtenu de réponse malgré N répétitions...
|
||||
// ==>>> Si oui, c'est ici qu'il faut le mettre....
|
||||
|
||||
m_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 (m_bus.down.ptr_debut_buffer_cdes != m_bus.down.ptr_fin_buffer_cdes) // Cas où il y a une commande en attente d'émission...
|
||||
{
|
||||
// ATTENTION : gérer les priorités ...!
|
||||
|
||||
m_bus.down.reponse.etat = M_BUS_REPONSE_ETAT_REPOS; // On prépare le traitement de la réponse à venir.
|
||||
|
||||
if (++ m_bus.down.ptr_debut_buffer_cdes == M_BUS_MAX_TAILLE_BUFFER_CDES) m_bus.down.ptr_debut_buffer_cdes = 0;
|
||||
|
||||
#ifdef __DEBUG_M_BUS
|
||||
m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].cde[m_bus.down.buffer_cdes[m_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.
|
||||
if (m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].mode_protocole != M_BUS_PROTOCOLE_DATA_BINAIRE) affichage_debug_bus(TYPE_BUS_DEBUG_M_BUS, "Tx", (char *) m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].cde, __DEBUG_M_BUS);
|
||||
else
|
||||
{
|
||||
sprintf(tmp, "[%i data bytes]", m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].lg_cde);
|
||||
affichage_debug_bus(TYPE_BUS_DEBUG_M_BUS, "Tx", tmp, __DEBUG_M_BUS); // Cas d'une réponse en mode binaire
|
||||
}
|
||||
#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;
|
||||
|
||||
for (i=0; (i < m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].lg_cde) && (lg_tx_buffer < M_BUS_MAX_TAILLE_BUFFER_TX); i++)
|
||||
{
|
||||
tx_buffer[lg_tx_buffer ++] = m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].cde[i];
|
||||
}
|
||||
|
||||
if (m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].mode_protocole != M_BUS_PROTOCOLE_DATA_BINAIRE)
|
||||
{
|
||||
tx_buffer[lg_tx_buffer ++] = ASCII_CR;
|
||||
}
|
||||
|
||||
//.............................
|
||||
// Envoi au driver d'émission :
|
||||
write(config_serial0.filestream, tx_buffer, lg_tx_buffer);
|
||||
|
||||
//..........................................................
|
||||
// Mise à jour des paramètres après l'émission de la trame :
|
||||
m_bus.down.flag_attente_reponse = TRUE;
|
||||
m_bus.protocole_tx.sequenceur.compteur_time_out = m_bus.down.buffer_cdes[m_bus.down.ptr_debut_buffer_cdes].time_out;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
default :
|
||||
{
|
||||
sprintf(tmp, "L'état du séquenceur M-Bus.Protocole_Tx est inconnu [%i]. Il est repositionné au REPOS", m_bus.protocole_tx.sequenceur.etat);
|
||||
affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR);
|
||||
m_bus.protocole_tx.sequenceur.etat = ETAT_SEQUENCEUR_M_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 m_bus_next_write_buffer_cdes(uint8_t priorite)
|
||||
{
|
||||
char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG];
|
||||
|
||||
|
||||
// !!! La gestion des priorités n'est pas traitée ! A vérifier mais si on écrase le début, celui-ci est probablement en cours d'utilisation...
|
||||
// Donc ATTENTION !!!!
|
||||
|
||||
|
||||
// Incrémentation :
|
||||
if (++ m_bus.down.ptr_fin_buffer_cdes == M_BUS_MAX_TAILLE_BUFFER_CDES) m_bus.down.ptr_fin_buffer_cdes = 0;
|
||||
|
||||
// Vérification si buffer plein :
|
||||
if (m_bus.down.ptr_fin_buffer_cdes == m_bus.down.ptr_debut_buffer_cdes)
|
||||
{
|
||||
// Décrémentation du pointeur puisqu'on ne va pas accepter la nouvelle commande qui n'a pas une priorité suffisante :
|
||||
if (m_bus.down.ptr_fin_buffer_cdes == 0) m_bus.down.ptr_fin_buffer_cdes = (M_BUS_MAX_TAILLE_BUFFER_CDES - 1);
|
||||
else m_bus.down.ptr_fin_buffer_cdes --;
|
||||
|
||||
// Message de débug :
|
||||
sprintf(tmp, "Buffer de commandes M-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) 'M', 0, NULL);
|
||||
|
||||
return(-1);
|
||||
}
|
||||
else return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user