1
0
Fork 0
mirror of https://github.com/cytech-ing-2023-2026/bcgv.git synced 2026-04-17 03:58:15 +02:00
Graded project for CY Tech's Hardware/Software Interface course
  • C 86.8%
  • Scala 10%
  • Makefile 2.9%
  • Shell 0.3%
Find a file
2026-02-28 11:01:35 +01:00
docker feat: Add working state machines (#4) 2026-02-20 11:42:24 +01:00
lib fix: Add missing driver files 2026-01-29 11:18:31 +01:00
model build: Treat all warnings as errors 2026-02-28 11:01:35 +01:00
src misc: Cleanup code 2026-02-28 10:58:35 +01:00
.clang-format feat: Final tweaks (#7) 2026-02-27 18:28:07 +01:00
.gitignore feat: Final tweaks (#7) 2026-02-27 18:28:07 +01:00
Doxyfile feat: Add base project layout 2026-01-29 09:52:03 +01:00
driver fix: Add missing driver files 2026-01-29 11:18:31 +01:00
Makefile build: Treat all warnings as errors 2026-02-28 11:01:35 +01:00
README.md docs: State in README that model.csv contains comments 2026-02-27 18:31:13 +01:00

BCGV

Rendu de DIZIN Jordan et FROMENTIN Raphaël pour le projet HSI en INEM.

Questions 1 & 2

Nous avons choisi de représenter nos données sous la forme d'un seul tableau CSV avec commentaires. Le schéma de base fourni dans le PDF ne semblait pas exactement couvrir nos besoins ainsi nous l'avons adapté en respectant le plus possible le matériel original.

Le script de génération de code a été fait avec le langage Scala qui représentait un bon mélange entre script, programmation fonctionnelle et ADT, trois fonctionnalités très utiles pour cette tâche.

Note : le script en lui-même nécessite Scala-CLI mais si vous avez la version compilée en .jar ou en exécutable natif (livrés en même temps que le projet), vous pouvez l'utiliser en (dé)commentant une ligne dans le Makefile du sous-projet.

Question 3

La fonction main se trouve dans app.c. Elle ouvre la connexion au driver via drv_open() (avec retry en cas d'échec), puis entre dans une boucle infinie où elle appelle drv_read_udp_100ms — un appel bloquant qui sert de séquenceur à 100 ms. La trame UDP reçue (15 octets) est ensuite décodée et affichée. La compilation produit l'exécutable app dans bin/, linké avec drv_api.a (cf. le Makefile).

Question 4

Chaque machine à états de l'annexe 2 est implémentée dans son propre fichier .c/.h sous src/fsm/ : low_beam, high_beam, parking_lights, left_blinker, right_blinker, hazard et wipers.

Toutes s'appuient sur le moteur générique fsm.c / fsm.h qui fournit la structure fsm_t, la recherche de transition et la consommation d'événements. Pour chaque FSM :

  • Les états et événements sont définis dans des headers partagés (lights.h, blinker.h, wipers.h).
  • Un tableau de transitions statique lie (état, événement) → (callback, état suivant).
  • Une fonction *_get_next_event (l'event supplier) décode les trames COMODO/BGF reçues et pousse les événements dans la file.
  • Les callbacks de transition pilotent les commandes BGF et mettent à jour la trame MUX d'envoi.
  • Un mécanisme de timer (décompté à chaque tick de 100 ms) génère automatiquement l'événement FSM_EV_TIMER pour les acquittements avec timeout.

Chaque FSM est instanciée via une fonction new_*_fsm() exposée dans son .h, puis stockée dans un tableau dans le main. À chaque itération de la boucle (cadencée à 100 ms), fsm_consume_comodo est appelée sur chaque FSM pour traiter les trames série et consommer les événements.

Question 5

La compilation repose sur deux Makefiles :

  • Le Makefile maître à la racine compile l'application (bin/app) en linkant les sources C de src/ avec drv_api.a et la bibliothèque générée. Il délègue la construction de la bibliothèque statique au sous-projet via $(MAKE) -C model.
  • Le Makefile du modèle génère le code C depuis le CSV, compile model.o et produit la bibliothèque statique model.a via ar rcs.

Un simple make à la racine déclenche les deux. La cible make run lance le driver puis l'applicatif (./driver & suivi de bin/app), faisant office de script de lancement.

Question 6

Les fonctions de décodage se trouvent dans src/protocols/recv/ :

  • COMODO (comodo.c / comodo.h) : la trame série de 1 octet (little-endian, périodique 500 ms) est décodée bit par bit via des masques. Chaque commande (warning, veilleuses, croisement, route, clignotants G/D, essuie-glaces, lave-glace) est extraite par une fonction comodo_cmd_* retournant un booléen.

  • MUX → BCGV (mux.c / mux.h) : la trame UDP de 15 octets (big-endian, périodique 100 ms) est décodée dans decode_mux_recv. Les champs sont extraits selon leurs offsets (n° de trame, kilométrage en 4 octets BE, vitesse, problèmes châssis/moteur/batterie, niveau réservoir, tours/minute en 4 octets BE). Un CRC-8 (polynôme 0x31, cf. libcrc) est vérifié sur les 14 premiers octets. Les accesseurs générés depuis le modèle CSV (set_mux_recv_data_*) peuplent la structure applicative mux_recv_data_t.

Question 7

Les fonctions d'encodage se trouvent dans src/protocols/ :

  • BCGV → BGF (bgf.c / bgf.h) : chaque message BGF (2 octets) est encodé par encode_bgf_frame — octet 0 = id du message (0x01 veilleuses, 0x02 croisement, 0x03 route, 0x04 clignotant droit, 0x05 clignotant gauche), octet 1 = activation (0/1). L'envoi se fait via send_bgf_frame sur la ligne série. Le BGF répond par un acquittement identique, traité dans les FSM avant de confirmer l'état.

  • BCGV → MUX (send/mux.c / send/mux.h) : la trame UDP 200 ms (10 octets, big-endian) est construite par encode_mux_send. Deux octets de flags (bit-fields) contiennent les voyants du tableau de bord (veilleuses, croisement, route, essence, défaut moteur, pression pneus, batterie, warning, panne batterie, température LDR, pression moteur, surchauffe huile, défaillance freins, essuie-glaces, lave-glace). Les 8 octets suivants encodent le kilométrage (4 octets BE), la vitesse (1 octet), le niveau réservoir (1 octet) et les tours/minute divisés par 10 (2 octets BE). L'envoi se fait via send_mux_frame toutes les 200 ms (compteur loop_counter % 2).

Question 8

Le main dans app.c suit le diagramme fourni : initialisation → boucle bloquante sur drv_read_udp_100ms → vérification du numéro de trame → décodage UDP → lecture série (si nécessaire, toutes les 500 ms) → décodage série → algorithmes (FSM) → encodage et envoi MUX (toutes les 200 ms) → encodage et envoi BGF (asynchrone).

La vérification du numéro de trame est implémentée dans decode_mux_recv (recv/mux.c) : le numéro attendu est calculé (rebouclage 100 → 1) et comparé au numéro reçu. En cas de saut, un warning est loggé via fprintf(stderr) mais la trame est tout de même traitée normalement, conformément à la consigne.