Le moteur : gère la partie ingrate
Le user : produit le résultat !
Les liens entre les deux: le moins possibles !
Le moteur appelle toujours le même point d"entrée dans user.
c'est plus souple d'appeler
<<callUser ("Bouton1Presse");>>
que ce qui semble équivalent
<<callBouton1Presse;>>
Dans le deuxième au moment de la compilation tu dois avoir la fonction définie même si elle ne fait rien.
Dans le premier cas, si l'appui sur B1 ne t'intéreesse pas, tu n'as rien à faire.
C'est le moteur qui s'occupe de toute la partie bas niveau. Il boucle en permanence et génère les messages. Ce qui est actionné par le message n'est pas du ressort du moteur.
Par exemple tu detectes:
appui B1 à (t) => evt (bt1, state, t)
release B1 à (t+1) => evt (bt1, state, t+1)
Le moteur expédie les évènements à User.
User ne les traite pas. Le moteur s'en occupe donc
et décortique evt(boutons, state,t).
Le moteur voit arriver le deuxième evt
Son job est de générer un nouveau message "click"
quand il repère le séquence Press/Release dans un intervalle de temps déterminé.
- Code: Tout sélectionner
If LastTimebt1Pressed - evt(t) < 2000 then # 2000 est la durée en ms
#click repéré !
if evt(t) - Lastbt1Click < 1000 then # double click repéré
evt (BT1_Click,btstate,t) # envoie le message
else
evt (BT1_DBLClick,btstate,t) # envoie le message
endif
Lastbt1Click=evt(t);
endif
Tu vois qu'il est relativement facile dans le moteur d'implémenter une gestion d'evt sans interferer avec la partie User.
Dans un message évenement, il y a toujours en paramètre les données utiles:
evt ( NomType, # c'est quoi
data, # l'état de tout les boutons par exemple si message de bt
t) # le timestamp de l'evt
data c'est sans type ! Selon l'evt c'est rien, des bits d'état, un pointeur vers plus de data, vers une chaine de caractère... etc
En fait la séparation entre "moteur" et "user" se fait naturellement.
Par exemple l'obtention du pourcentage de bande passante utilisée par ftp est typiquement du mode user
Ta boucle actuelle doit inclure a un moment ou un autre les appels de ce genre de calcul.
Donc ça ce décompose comme suit:
Pendant l'init de 'user', 'user' a demandé au moteur de lui générer un message 'Timer' toutes les X secondes et un autre Y secondes.
Donc toutes les X secondes l'evt est généré et dans user tu trouves:
...
case Timer1: # Il est temps de recalculer les infos
buffer="bp FTP=" & calculeftp() & "kb/s"
print (L1,buffer) #appele une API du moteur
#ligne 2 si bt4 est appuyé l'info change !
if (mybt4)
buffer="Peak user connected:" & calculeXYZ()
else
buffer="Actual user connected:" & calculeXY()
endif
print (L2,buffer);
updateLcd; # déclenche un une fois
# l'affichage effectif
case Timer2: # Un deuxième Timer Y seconde actualise moins souvent cette
# info qui demande beaucoup de calcul !
...
buffer= "Ce long texte défile en continue sur une ligne du LCD et fournit un max d'informations générales";
defiler_text (L3,buffer)
...
Tu vois bien mieux la séparation je pense non ?
Ainsi un truc casse $%#&! comme faire défiler un texte est gérer par le moteur.
Deux ou trois evt associé à ça, une API minimale
defiler_setspeed()
defiler_pause(x)
C'est dur à mettre en place mais maintenant que tu maitrises bien la gestion du LCD et bouton c'est pas compliqué de faire la séparation entre les deux niveaux (moteur,user).
Bien sur tu fournis toujours le code "User" pour ipcop de base. Mais il devient facile pour n'importe qui d'écrire d'autre "User" du moment que tout passe par message et API.
Tandis que "moteur" peut toujours étendre les fonctions chiantes à gérer
au fur et a mesure. Par exemple un "menu" !
"User" appelle Domenu(L4,"choix 1","choix 2","choix 3", "choix 4","choix 5");
Le moteur répond en envoyant des événements simples comme
evt (MENU, item1selected)
Faut surtout pas faire tout d'un coup mais partir sur une base souple et robuste !
Est-ce que tu le sens ou pas ? Si le schema est clair dans ta tète, ca doit pas être trop long à retrouver ce qui correspond à l'API moteur et à "User" et bien sur à coder .