Plusieurs variables sur un offset

Avro

PILOTE DE LIGNE
Messages
1 904
Réactions
283
Points
309
Bonjour à  tous,

second épisode dans mes tutos SIOC et aussi .lua

Au début, jutilisais un offset par fonction. Un offset d'une longueur de 1 comprend 8 bits qui sont numérotés de 0 à  7.

Le bit 0 correspond à  la valeur 1, le bit 1 correspond à  la valeur 2, le bit 2 correspond à  la valeur 4 etc. Ce sont des puissances de 2. Autrement dit le bit 7 vaut 2 puissance de 7 soit 128.

Dans le code suivant OVH vaut donc 1.

Code:
[== SIOC ==]
Var 500, name OVH, Link FSUIPC_INOUT, Offset $3344, Length 1
Var 501, name GEN1_SW, Link IOCARD_SW, Input 0
{
  IF &GEN1_SW = 0
  {
    &OVH = SETBIT 0
  }
  ELSE
  {
    &OVH = CLEARBIT 0
  }
}

Dans mon script .lua je vais vérifier cette valeur.

Code:
[== LUA ==]
    -- bouton 0
    ovh= ipc.readUB(0x3344)
    if ovh == 1 then
        ipc.writeLvar("L:elec_gen1_switch_clicked",1)
    else
        ipc.writeLvar("L:elec_gen1_switch_clicked",2)
    end

Si mon offset 3344 a une valeur de 1 alors on génère de lélectricité à  partir de la puissance du moteur 1. Mon offset 3344 avec le bit 0 sera vu dans FSUIPC comme le bouton 0 du joystick 65. Je lassocie avec mon script .lua ci-dessus et ça marche.

Ce code a un inconvénient, je n'utilise par les bits 1, 2, 3, 4, 5, 6 et 7 ; quel gâchis.

Malheureusement, rien n'est jamais simple

On veut contrôler que le bit 0 est activé par mon interrupteur. Pour cela je le vérifie en observant la valeur de l'offset 3344. Quand un seul interrupteur est sur ON, tout va bien. Mais si j'active un autre interrupteur.

Code:
[== SIOC ==]
Var 503, name GEN4_SW, Link IOCARD_SW, Input 3
{
  IF &GEN4_SW = 1
  {
    &OVH= SETBIT 1
  }
  ELSE
  {
    &OVH= CLEARBIT 1
  }
}

Quand je déclenche mon Générateur du moteur 4 mon offset 3344 va ajouter à  la valeur courante 2 puissance de 1 soit 2. Comme le premier interrupteur est sur ON, mon offset va prendre la valeur 3 (1 + 2).

Mon script .lua

Code:
[== LUA ==]
    -- bouton 0
    ovh= ipc.readUB(0x3344)
    if ovh == 1 then
        ipc.writeLvar("L:elec_gen1_switch_clicked",1)
    else
        ipc.writeLvar("L:elec_gen1_switch_clicked",2)
    end

ne fonctionnera pas dans tous les cas puisque mon offset 3344 pourra prendre la valeur 1 ou 2 ou 3.

J'ai un peu pataugé, alors pour éviter une grande frustation, je vais vous expliquer comment faire.

Au lieu de tester : if ovh == 1 then, je vais vérifier par exemple que 3 contient 2 puissance de 0. On écrit par convention 2 ^ 0

Par exemple, si j'utilise 3 interrupteurs avec les bits 0, 1 et 2. Si j'active :

l'interrupteur 1, j'ai 1 (2 ^ 0)
les interrupteurs 1 et 2, j'ai 3 ( 2 ^ 0 + 2 ^ 1 )
les interrupteurs 1, 2 et 3, j'ai 7 ( 2 ^ 0 + 2 ^ 1 + 2 ^ 2 )
les interrupteurs 1 et 3, j'ai 5 ( 2 ^ 0 + 2 ^ 2 )

Ce qu'il faut arriver à  faire c'est quand j'ai 5, quels sont les interrupteurs sur ON. Ben, 1 et 3. Oui mais on va le faire de manière mathématique car sinon, c'est lenfer.

C'est niveau math sup cette histoire ! Peut-être, mais Google est aussi mon ami :)

Mieux que Google, il y a Greg qui ma donné une solution plus simple.

Code:
[== LUA ==]
ovh = ipc.readUB(0x3340)
if logic.And(ovh, 2 ^ 0) ~= 0 then
   ipc.writeLvar("L:elec_gen1_switch_clicked",1)
else
   ipc.writeLvar("L:elec_gen1_switch_clicked",2)
end

La fonction if logic.And(ovh, 2 ^ 0) ~= 0 va tester que le bit 0 est vrai.

Certaines de mes LVAR sont des bascules simples. La même variable fait passer interrupteur de la position ON à  OFF ou de OFF à  ON en utilisant par exemple la commande ipc.writeLvar("L:fuel_l_inner_pump_feed_switch_clicked",1). Dans ce cas, pas besoin de faire de test.

Et voilà , super simple, hein


##################### Solution plus compliquée #####################

Ci-dessous la solution que j'avais trouvée que je conserve ici pour mémoire.

Code:
[== LUA ==]
    function hasbit(x, p)
      return x % (p + p) >= p
    end

    -- bouton 23
    ovh = ipc.readUB(0x3340)
    if hasbit(ovh, 2 ^ 0) then
        ipc.writeLvar("L:elec_gen1_switch_clicked",1)
    else
        ipc.writeLvar("L:elec_gen1_switch_clicked",2)
    end

J'ai remplacé mon test par celui-ci : if hasbit(ovh, 2 ^ 0) then
Ce test utilise une fonction, hasbit qui est déclarée en tête de script

Code:
[== LUA ==]
    function hasbit(x, p)
      return x % (p + p) >= p
    end

Cette fonction va retourner true (vrai) ou false (faux)

ovh = 5 et je dois tester si 5 contient le bit 0, soit 2 ^ 0

La fonction va vérifier que : 5 % (1+1) >= 1

% est un modulo ou dit plus simplement le reste d'une division. 5 / 2 = 2 reste 1. Si je souhaite savoir le reste je peux écrire plus simplement : 5 % 2 et le résultat est 1

Ce qui veut dire ici que la condition est vrai puisque le reste de la division de 5 / 2 est égale ou supérieure à  1 ; jexécute donc la commande : ipc.writeLvar("L:elec_gen1_switch_clicked",1).
 
Hello,

Merci pour les explications.
Ce que vous voulez faire c'est tester la valeur d'un bit particulier ? Je pense que les fonctions de base peuvent suffire par ex. votre code peut devenir quelque chose du type :
Code:
ovh = ipc.readUB(0x3340)
if logic.And(ovh, 2 ^ 1) ~= 0 then
   ipc.writeLvar("L:elec_gen1_switch_clicked",1)
else
   ipc.writeLvar("L:elec_gen1_switch_clicked",2)
end

De même, vous pourriez définir avant une table des valeurs à  tester par ex. pour L:elec_gen1_switch_clicked affecter une variable elecgen1 à  1 comme valant le 1er bit, une autre variable à  2, etc. pour remplacer la ligne if logic.And(ovh, 2 ^ 1) ~= 0 then par if logic.And(ovh, 2 ^ elecgen1) ~= 0 then par exemple.

Cela offre aussi la possibilité de tester la présence de plusieurs bits positionnés à  la fois par ex. if logic.And(ovh, (2 ^ elecgen1 + elecgen2)) ~= 0

La lecture du code peut être plus claire.

Ces remarques seulement pour aider si possible pas pour critiquer d'une manière bien maladroite le travail proposé par son auteur : bon code
 
Bonjour Greg,

merci, je n'avais pas trouvé la fonction logic.And. Je vais modifier mon tuto en conséquence.

J'ai un doute sur :

if logic.And(ovh, (2 ^ elecgen1 + elecgen2)) ~= 0

Si je les remplace par mes valeurs, cela donnerait :

if logic.And(ovh, (2 ^ 1 + 2)) ~= 0 soit
if logic.And(ovh, (2 + 2)) ~= 0

Le bit 4 est dans mon utilisation affecté au générateur de l'APU. Ou bien, ya un truc que je n'ai pas compris.
 
hahahaha on était tous à  la même ce weekend. Mon beau frère ma pondu ça:

Code:
[== LUA ==]
var = ipc.readUB(0x3340)

   if (math.mod(var,2) == 1) then
      ipc.writeLvar("L:OHD_DC_CNTRL_PNL_STB_SW",1)
   else
      ipc.writeLvar("L:OHD_DC_CNTRL_PNL_STB_SW",0)
   end
   
   var1 = math.floor(var/2)
   
   if (math.mod(var1,2) == 1) then
      ipc.writeLvar("L:OHD_DC_CNTRL_PNL_AUX_SW",1)
   else
      ipc.writeLvar("L:OHD_DC_CNTRL_PNL_AUX_SW",0)
   end

J'ai pas tout retenu ce qui ma expliqué mais j'ai entendu parler d'un modulo. A 1h du matin dimanche, il ma encore envoyé un whattsapp pour le dire que pour les interr à  3 états, faudra mémorisé les 2 bits et les comparer pour déduire les différents états :eek:
Ca va encore me coûter une pizza :cool:
 
et je me suis pondu ça pour un interr à  3 positions:

Code:
[== LUA ==]
   var1 = math.floor(var/2)
   var2 = math.floor(var/4)
   
   if (math.mod(var1,2) == 1) then
      ipc.writeLvar("L:OHD_EMER_LT_CAUT_TEST_SW",-1)
   elseif (math.mod(var2,2) == 1) then
      ipc.writeLvar("L:OHD_EMER_LT_CAUT_TEST_SW",1)
   else
      ipc.writeLvar("L:OHD_EMER_LT_CAUT_TEST_SW",0)
   end

Bref, je sais pas si ça peut aider mais Greg ou Avro nous le dirons surement...
 
C'est une autre manière de le faire mais la solution de greg est la plus simple. Adoptée :) Tuto modifié.
 
Yes top la solution à  Greg, adoptée aussi. Merci ! :) :) :)
 
Hello,

Bonne nouvelle alors, surtout bravo pour avoir exploité les explications peut-être pas claires O:)

Oui, j'ai fait une erreur pour le test "multi-bit" :
if logic.And(ovh, (2 ^ elecgen1 + elecgen2)) ~= 0 est FAUX, il faut lire :
if logic.And(ovh, (2 ^ elecgen1 + 2 ^ elecgen2)) ~= 0, désolé

Pour inf°, votre raisonnement passé était correct, mais il y a une erreur de calcul ici que je viens de voir en relisant :
...à  trois positions car 2 ^ 0 = 0 est erroné, il faut calculer :
...à  trois positions car 2 ^ 0 = 1 ; mathématiquement, n'importe quoi ^ 0 vaut 1 ; c'est pour cela que le bit 1 peut quand même être inclus (avec un autre bit) dans un calcul à  3 positions.

Ex. si bit 3 et 1 utilisés, 5 sera la valeur indiquant que ces 2 bits sont positionnés.
 
Merci greg, je ne savais pas du tout que n ^ 0 était égal à  1 :) Je devais dormir ce jour là  Tuto corrigé.
 
Bonjour,

Les offsets 0350 et 311E permettent de gérer les fréquences NAV 1, respectivement les fréquences active et standby. La documentation FSUIPC indique que ces offsets sont de type BCD

Doc FSUIPC a dit:
NAV1 frequency, 4 digits in BCD format. A frequency of 113.45 is represented by 0x1345. The leading 1 is assumed.
Fréquence NAV1, 4 chiffres au format BCD. Une fréquence de 113,45 sera représentée par 0x1345. Le préfixe 1 est présumé.

Pour avoir un affichage cohérent sur un display 7 digits, il faut passer par la fonction FROMBCD. Nous prendrons pour cet exemple une fréquence active VHF NAV 1 de 113.45.

Code:
[== SIOC==]
Var 0611, Name VHF_NAV, Link IOCARD_DISPLAY, Device 2, Digit 0, Numbers 5 
Var 0612, name VHF_NAV_INDIQ, Link FSUIPC_INOUT, Offset $0350, Length 2
{
   L0 = FROMBCD &VHF_NAV_INDIQ
   &VHF_NAV = L0 + 10000
}

Les numéros de Var, Device, Digit dépendent de votre configuration matériel.

Que fait le script ?

Code:
Var 0611, Name VHF_NAV, Link IOCARD_DISPLAY, Device 2, Digit 0, Numbers 5

Il définit une variable VHF_NAV en lien avec le premier afficheur de 5 chiffres de la carte 2

Code:
Var 0612, name VHF_NAV_INDIQ, Link FSUIPC_INOUT, Offset $0350, Length 2
{
   ...
}

La variable VHF_NAV_INDIQ va lire l'offset 0350. Cet offset comprend 4 chiffres qui se codent en 12 bits soit 2 octets. La valeur de l'offset est décimal codé bin'aire (BCD). C'est à  dire que la valeur 1345 est codé 10101000001.

Code:
Var 0612, name VHF_NAV_INDIQ, Link FSUIPC_INOUT, Offset $0350, Length 2
{
   L0 = FROMBCD &VHF_NAV_INDIQ
   ...
}

Il crée la variable intermédiaire L0 avec la conversion bin'aire => décimal soit 1345

Code:
Var 0612, name VHF_NAV_INDIQ, Link FSUIPC_INOUT, Offset $0350, Length 2
{
   ..
   &VHF_NAV = L0 + 10000
}

Laffichage additionnera à  la valeur 1345 10000 pour aboutir à  la fréquence 11345. Restera à  définir la position de la virgule.
 
Retour
Haut