Attribute VB_Name = "SrcModule"
Option Explicit

Public Enum EModeleBras
    Aucun = 0
    V8_3_Injecteurs = 1
    V8_8_Injecteurs = 2
    V9_3_Injecteurs = 3
    V9_8_Injecteurs = 4
    V10_3_Injecteurs = 5
    V10_8_Injecteurs = 6
    V13_3_Injecteurs = 7
    V13_8_Injecteurs = 8
    V16_3_Injecteurs = 9
    V16_8_Injecteurs = 10
    V17_3_Injecteurs = 11
    V17_8_Injecteurs = 12
    V20_8_Injecteurs = 13
End Enum

Public Const MAX_INJECTEUR = 8
Public Const MAX_BRAS = 8
Public Const MAX_PORT = 16
Public Const MAX_NUMERO = 100



Public Type TLiaison
    Port As Integer
    RxFrame As Long
    TxFrame As Long
    RxFrameReject As Long
    
    RXSlave As Integer
    TXSlave As Integer
End Type


Public Type TTisi
    Disponible As Boolean
    Numero As Integer
    
    
    RxFrame As Long
    TxFrame As Long
    
    
    ' Données Reçues
    ' ==============
    RxAffichage(5) As String * 16
    RxSortie(4) As Boolean
    RxBits(4) As Boolean
    
    RxEtendu(240) As Byte
    
    RxEtenduModeMarche As Byte
    RxEtenduTypeData As Byte
    RxEtenduCodeLangue As Byte
    RxEtenduNumeroQuai As Byte
    RxEtenduTotalRecord As Byte
    RxEtenduFirstRecordBloc As Byte
    RxEtenduRecordQuantityBloc As Byte
    
    TxEtendu(240) As Byte
    
    TxEtenduModeMarche As Byte
    TxEtenduTypeData As Byte
    TxEtenduTotalRecord As Byte
    TxEtenduFirstRecordBloc As Byte
    TxEtenduRecordQuantityBloc As Byte
    
    ' Données Emises
    ' ==============
    TxNumeroBadgeG As String * 40
    TxNumeroBadgeD As String * 40
    TxBadgePresentG As Boolean
    TxBadgePresentD As Boolean
    TxClavierG As Long
    TxClavierD As Long
    TxETOR As Long
    TxSTOR As Long
    
    
    ' Zones Modbus
    Lecture1ModbusDebut As Long
    Lecture1ModbusFin As Long
    Lecture1ModbusLongueur As Long
    
    Lecture2ModbusDebut As Long
    Lecture2ModbusFin As Long
    Lecture2ModbusLongueur As Long
    
    ' Compartimentage
    Lecture3ModbusDebut As Long
    Lecture3ModbusFin As Long
    Lecture3ModbusLongueur As Long
    
    
    Ecriture1ModbusDebut As Long
    Ecriture1ModbusFin As Long
    Ecriture1ModbusLongueur As Long
    
    Ecriture2ModbusDebut As Long
    Ecriture2ModbusFin As Long
    Ecriture2ModbusLongueur As Long
    
    Ecriture3ModbusDebut As Long
    Ecriture3ModbusFin As Long
    Ecriture3ModbusLongueur As Long
    
    Ecriture4ModbusDebut As Long
    Ecriture4ModbusFin As Long
    Ecriture4ModbusLongueur As Long
    
    Ecriture5ModbusDebut As Long
    Ecriture5ModbusFin As Long
    Ecriture5ModbusLongueur As Long
    
    ' Compartimentage
    Ecriture6ModbusDebut As Long
    Ecriture6ModbusFin As Long
    Ecriture6ModbusLongueur As Long
    
    
End Type

Public Type TPont
    Disponible As Boolean
    Numero As Integer
    
    RxFrame As Long
    TxFrame As Long
    
    
    CodeCommande As Long
    Masse As Long
    NumeroDSD As Long
    
    Lecture1ModbusDebut As Long
    Lecture1ModbusFin As Long
    Lecture1ModbusLongueur As Long
    
    Lecture2ModbusDebut As Long
    Lecture2ModbusFin As Long
    Lecture2ModbusLongueur As Long
           
    Ecriture1ModbusDebut As Long
    Ecriture1ModbusFin As Long
    Ecriture1ModbusLongueur As Long
    
    Ecriture2ModbusDebut As Long
    Ecriture2ModbusFin As Long
    Ecriture2ModbusLongueur As Long
    
End Type

Public Type TInjecteur
    Disponible As Boolean
    TrancheInjectee As Integer
    TxTaux As Integer
    TxTotalisateur As Long
End Type

Public Type TBras
    Disponible As Boolean
    Numero As Integer
    Modele As EModeleBras
    
    
    ' Zones Modbus
    LectureModbusDebut As Long
    LectureModbusFin As Long
    LectureModbusLongueur As Long
    
    
    EcritureModbusDebut As Long
    EcritureModbusFin As Long
    EcritureModbusLongueur As Long
    
    
    RxFrame As Long
    TxFrame As Long
    
    ' Données Reçues
    ' ==============
    RxProduit As Integer
    RxAdditif As Integer
    RxColorant As Integer
    RxQuota As Long
    RxDejaChargee As Long
    RxTemperatureDejaChargee As Single
    RxCodeDefaut As Long
    RxLibelleDefaut As String * 10
    RxLibelleProduit As String * 6
    RxLibelleAdditif As String * 6
    RxLibelleColorant As String * 6
    RxPPMAdditif As Single
    RxPPMColorant As Single
    RxAutorisationCalculateur As Boolean
    RxAutorisationClient As Boolean
    RxVolumeControle As Long
    RxPriseEnCompteVolume As Boolean
    RxVolumeReleve As Boolean
    RxAcquit As Boolean
    RxPresenceSondeCamion As Boolean
    RxCustomOutPut1 As Boolean
    RxCustomOutPut2 As Boolean
    RxIdentifiantAutorisation As Long
    
    RxBlendingRun As Long
    RxBlendingRate As Long
    
    MemoIDBe As Long
    
    ' Données Emises
    ' ==============
    TxDebit As Integer
    TxTemperatureInstantannée As Single
    TxTemperatureMoyenne As Single
    TxAffichage As String * 10
    TxPression As Single
    TxTV As Single
    TxVolume As Long
    TXFuite As Long
    TxPrede As Long
    TxIdentifiantAutorisation As Long
    TxVolumeAdditif As Long
    TxVolumeColorant As Long
    TxCodeDefaut As Long
    TxSondeAPi As Boolean
    TxTerre As Boolean
    TxTerreD As Boolean
    TxBrasVapeur As Boolean
    TxDemandeChargement As Boolean
    TxDemandeChargementD As Boolean
    TxDemandeProduit As Boolean
    TxDemandeReleve As Boolean
    TxPriseEnCompteCorrecte As Boolean
    
    TxForcageDemandeReleve As Boolean
    TxForcagePriseEnCompteCorrecte As Boolean
    TxBrasBaisse As Boolean
    TxPasserelleG As Boolean
    TxPasserelleD As Boolean
    TxOrientationG As Boolean
    TxOrientationD As Boolean
    
    
    TxTotalisateur As Long
    TxInjecteurAdditif As Long
    TxInjecteurColorant As Long
    TxAutonome As Boolean
    TxCustomInput1 As Boolean
    TxCustomInput2 As Boolean
    TxPSL As Boolean
    TxDemandeAcquit As Boolean
    TxChangementBE As Boolean
    ChangementBEEnCours As Boolean
    
    TxRecopieGD As Boolean
    TxRecopiePD As Boolean
    TxPresenceTicket As Boolean
    
    CoeffBlending As Long
    TxBlendingTotalisateur As Long
    TxBlendingVolume As Long
    TxBlendingRate As Single
    TxBlendingTemperature As Single
    TxBlendingTemperatureMoyenne As Single
    
    Injecteur(MAX_INJECTEUR) As TInjecteur
    
    ' Données Interne
    ' ===============
    MarcheAuto As Boolean
    Increment As Single
    VolumeAuto As Single
    VolumeTotalisateur As Single
    Modulo As Boolean
    Injection As Boolean
    Tranche As Integer
    UpdateWindows As Boolean
    
End Type

Public Type TValeurDefaut
    Debit As Integer
    Temperature As Single
    Pression As Single
    Prede As Long
End Type

Public Type TSimulateur
    Marche As Boolean
    Phase As Integer
    LastRxQueue As Integer
    RxQueue As Integer
    
    Liaison As TLiaison
    Tisi As TTisi
    Pont As TPont
    Bras(MAX_BRAS) As TBras
    ValeurParDefaut As TValeurDefaut
End Type

Public Simulateur As TSimulateur



Public Sub InitSimulateurData()
Dim xbras As Integer

Simulateur.Marche = False
' Liaison
Simulateur.Liaison.Port = 2

' Tisi
Simulateur.Tisi.Disponible = True
Simulateur.Tisi.Numero = 10
' Bras
For xbras = 1 To MAX_BRAS
    Simulateur.Bras(xbras).Disponible = True
    Simulateur.Bras(xbras).Numero = xbras
    Simulateur.Bras(xbras).Modele = V8_8_Injecteurs
Next xbras

' Valeur par défaut
' =================
Simulateur.ValeurParDefaut.Debit = 500
Simulateur.ValeurParDefaut.Prede = 1000
Simulateur.ValeurParDefaut.Pression = 0
Simulateur.ValeurParDefaut.Temperature = 12.3


End Sub

Public Sub SimulateurMarche()
' Calcul des zones Modbus
' =======================
SimulateurSetModbusArea

Simulateur.Marche = True

Debug.Print " ========================="
Debug.Print " MISE EN MARCHE SIMULATEUR"
Debug.Print " ========================="

End Sub

Public Sub SimulateurStop()
Simulateur.Marche = False

End Sub

Public Sub SimulateurSetModbusArea()
' Fixe les zones modbus suivant de chaque équipement
' ==================================================
Dim i As Integer
Dim j As Integer

Simulateur.Tisi.Ecriture1ModbusDebut = 0
Simulateur.Tisi.Ecriture1ModbusLongueur = 82
Simulateur.Tisi.Ecriture1ModbusFin = Simulateur.Tisi.Ecriture1ModbusFin + Simulateur.Tisi.Ecriture1ModbusLongueur

Simulateur.Tisi.Ecriture2ModbusDebut = 82
Simulateur.Tisi.Ecriture2ModbusLongueur = 46
Simulateur.Tisi.Ecriture2ModbusFin = Simulateur.Tisi.Ecriture2ModbusDebut + Simulateur.Tisi.Ecriture2ModbusLongueur

Simulateur.Tisi.Ecriture3ModbusDebut = 122
Simulateur.Tisi.Ecriture3ModbusLongueur = 1
Simulateur.Tisi.Ecriture3ModbusFin = Simulateur.Tisi.Ecriture3ModbusDebut + Simulateur.Tisi.Ecriture3ModbusLongueur

Simulateur.Tisi.Ecriture4ModbusDebut = 127
Simulateur.Tisi.Ecriture4ModbusLongueur = 1
Simulateur.Tisi.Ecriture4ModbusFin = Simulateur.Tisi.Ecriture4ModbusDebut + Simulateur.Tisi.Ecriture4ModbusLongueur

Simulateur.Tisi.Ecriture5ModbusDebut = 260
Simulateur.Tisi.Ecriture5ModbusLongueur = 120
Simulateur.Tisi.Ecriture5ModbusFin = Simulateur.Tisi.Ecriture5ModbusDebut + Simulateur.Tisi.Ecriture5ModbusLongueur


Simulateur.Tisi.Ecriture6ModbusDebut = &H600
Simulateur.Tisi.Ecriture6ModbusLongueur = 120
Simulateur.Tisi.Ecriture6ModbusFin = Simulateur.Tisi.Ecriture6ModbusDebut + Simulateur.Tisi.Ecriture6ModbusLongueur



Simulateur.Tisi.Lecture1ModbusDebut = 140
Simulateur.Tisi.Lecture1ModbusLongueur = 86
Simulateur.Tisi.Lecture1ModbusFin = Simulateur.Tisi.Lecture1ModbusDebut + Simulateur.Tisi.Lecture1ModbusLongueur

Simulateur.Tisi.Lecture2ModbusDebut = 250
Simulateur.Tisi.Lecture2ModbusLongueur = 1
Simulateur.Tisi.Lecture2ModbusFin = Simulateur.Tisi.Lecture2ModbusDebut + Simulateur.Tisi.Lecture2ModbusLongueur

Simulateur.Tisi.Lecture3ModbusDebut = &H400
Simulateur.Tisi.Lecture3ModbusLongueur = 120
Simulateur.Tisi.Lecture3ModbusFin = Simulateur.Tisi.Lecture3ModbusDebut + Simulateur.Tisi.Lecture3ModbusLongueur


Simulateur.Pont.Lecture1ModbusDebut = 1
Simulateur.Pont.Lecture1ModbusLongueur = 110
Simulateur.Pont.Lecture1ModbusFin = Simulateur.Pont.Lecture1ModbusDebut + Simulateur.Pont.Lecture1ModbusLongueur

Simulateur.Pont.Lecture2ModbusDebut = 171
Simulateur.Pont.Lecture2ModbusLongueur = 1
Simulateur.Pont.Lecture2ModbusFin = Simulateur.Pont.Lecture2ModbusDebut + Simulateur.Pont.Lecture2ModbusLongueur

Simulateur.Pont.Ecriture1ModbusDebut = 15
Simulateur.Pont.Ecriture1ModbusLongueur = 1
Simulateur.Pont.Ecriture1ModbusFin = Simulateur.Pont.Ecriture1ModbusDebut + Simulateur.Pont.Ecriture1ModbusLongueur

Simulateur.Pont.Ecriture2ModbusDebut = 171
Simulateur.Pont.Ecriture2ModbusLongueur = 1
Simulateur.Pont.Ecriture2ModbusFin = Simulateur.Pont.Ecriture2ModbusDebut + Simulateur.Pont.Ecriture2ModbusLongueur



For i = 1 To MAX_BRAS
    Select Case Simulateur.Bras(i).Modele
    
    
        Case V8_3_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 13
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 27
        For j = 1 To 3
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
        
        Case V8_8_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 13
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 42
        For j = 1 To 8
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
    
        Case V9_3_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 15
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 30
        For j = 1 To 3
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
        
        Case V9_8_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 15
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 45
        For j = 1 To 8
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
    
        Case V10_3_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 18
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 33
        For j = 1 To 3
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
        
        Case V10_8_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 18
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 48
        For j = 1 To 8
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
    
        Case V13_3_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 18
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 34
        For j = 1 To 3
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
        
        Case V13_8_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 18
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 49
        For j = 1 To 8
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
    
        Case V16_3_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 29
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 34
        For j = 1 To 3
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
        
        Case V16_8_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 29
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 49
        For j = 1 To 8
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
    
        Case V17_3_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 31
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 38   ' 34
        For j = 1 To 3
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
        
        Case V17_8_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 31
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 57   ' 49
        For j = 1 To 8
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
    
        Case V20_8_Injecteurs
        Simulateur.Bras(i).EcritureModbusDebut = 0
        Simulateur.Bras(i).EcritureModbusLongueur = 34
        Simulateur.Bras(i).LectureModbusDebut = 0
        Simulateur.Bras(i).LectureModbusLongueur = 70
        For j = 1 To 8
            Simulateur.Bras(i).Injecteur(j).Disponible = True
            Simulateur.Bras(i).Injecteur(j).TxTaux = 100
        Next j
        
    
    
    End Select
    
    
    Simulateur.Bras(i).EcritureModbusFin = Simulateur.Bras(i).EcritureModbusDebut + Simulateur.Bras(i).EcritureModbusLongueur
    Simulateur.Bras(i).LectureModbusFin = Simulateur.Bras(i).LectureModbusDebut + Simulateur.Bras(i).LectureModbusLongueur
    
Next i




End Sub

Public Function AnalyseRx(RxBuffer() As Byte, RxSize As Integer, Esclave As Integer, Fonction As Integer, AdresseDebut As Long, Longueur As Long) As Boolean
' Analyse RxBuffer et
' Détermine le numéro d'esclave, le code fonction, l'adresse et la longueur
' =========================================================================
' Retourne True si Ok
' ===================

' Octet 0 : Esclave
' Octet 1 : Fonction
' Octets 2 et 3 : Adresse
' Octets 4 et 5 : Longueur

' Pour être analyser la longueur doit au moins être de 8 octets
If Not ProtocoleModbusCheckCRC16(RxBuffer(), RxSize - 1) Then
    If RxSize >= 8 Then
        ' ------------------
        ' vérification CRC16
        ' ------------------
    
        ' Extraction des données
        ' ======================
        Esclave = CInt(RxBuffer(0))
        Fonction = CInt(RxBuffer(1))
        AdresseDebut = (CLng(RxBuffer(2)) * &H100&) + CLng(RxBuffer(3))
        Longueur = (CLng(RxBuffer(4)) * &H100&) + CLng(RxBuffer(5))
        
    
    
        AnalyseRx = True
    End If
Else
    Debug.Print "Erreur CRC16"
End If

End Function

Public Function IsEsclaveOK(Esclave As Integer, Tisi As Boolean, Pont As Boolean, Bras As Integer) As Boolean
' Retourne True si l'esclave demandé est géré
' Dans ce cas On indique dans Tisi si tisi ou dans bras si bras
' =============================================================
Dim i As Integer
Tisi = False
Pont = False
Bras = 0

If Simulateur.Tisi.Disponible Then
    If Simulateur.Tisi.Numero = Esclave Then
        Tisi = True
        IsEsclaveOK = True
        Exit Function
    End If
End If

If Simulateur.Pont.Disponible Then
    If Simulateur.Pont.Numero = Esclave Then
        Pont = True
        IsEsclaveOK = True
        Exit Function
    End If
End If

For i = 1 To MAX_BRAS
    If Simulateur.Bras(i).Disponible Then
        If Simulateur.Bras(i).Numero = Esclave Then
            Bras = i
            IsEsclaveOK = True
            Exit Function
            
        End If
    End If
Next i

IsEsclaveOK = False
End Function

Public Function MakeReponseTisi(TxBuffer() As Byte, Fonction As Integer, AdresseDebut As Long, Longueur As Long) As Integer
' Construit la réponse
' ====================
Dim TxLen As Integer
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim x As Integer
Dim Lng As Long
Dim Mot As Integer
Select Case Fonction
    Case 3, 4   ' Lecture de mots
    If (AdresseDebut = Simulateur.Tisi.Lecture1ModbusDebut) Or (AdresseDebut = Simulateur.Tisi.Lecture2ModbusDebut) Then
        ' Dimensionnement de la trame
        i = Longueur * 2
        TxLen = 3 + i + 2
        ReDim TxBuffer(TxLen - 1)
        ' encodage Header
        ' ===============
        TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
        TxBuffer(1) = CByte(Fonction)
        TxBuffer(2) = CByte(Longueur * 2)
        ' Pas de données
        ' ==============
        
        If (AdresseDebut = Simulateur.Tisi.Lecture1ModbusDebut) Then
            ' Recopie Ecran
            Mot = 1
            k = 3
            For i = 1 To 5
                'Simulateur.Tisi.RxAffichage(i) = ""
                For j = 1 To 16
                    'If k <= FrameSize Then
                        'Mid$(Simulateur.Tisi.RxAffichage(i), j, 1) = Chr$(RxBuffer(k))
                    'End If
                    TxBuffer(k) = Asc(Mid$(Simulateur.Tisi.RxAffichage(i), j, 1))
                    k = k + 1
                Next j
                'Debug.Print Simulateur.Tisi.RxAffichage(i)
            Next i
        
        
            
            
            ' Numéro de badge Gauche
            ' ======================
            Mot = 45
            For j = 1 To 40
                TxBuffer(((Mot - 1) * 2) + 3 + j - 1) = Asc(Mid$(Simulateur.Tisi.TxNumeroBadgeG, j, 1))
            Next j
            
            ' Numéro de badge Droite
            ' ======================
            Mot = 65
            For j = 1 To 40
                TxBuffer(((Mot - 1) * 2) + 3 + j - 1) = Asc(Mid$(Simulateur.Tisi.TxNumeroBadgeD, j, 1))
            Next j
            
            
            ' Clavier central
            ' ===============
            Mot = 41
            Lng = 0
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            
            ' Claviers latéraux & Présence Badges
            ' ===================================
            Mot = 42
            Lng = 0
            If (Simulateur.Tisi.TxClavierG And &H1) = &H1 Then Lng = Lng Or &H100
            If (Simulateur.Tisi.TxClavierG And &H2) = &H2 Then Lng = Lng Or &H400
            If (Simulateur.Tisi.TxClavierG And &H4) = &H4 Then Lng = Lng Or &H200
            If (Simulateur.Tisi.TxClavierG And &H8) = &H8 Then Lng = Lng Or &H808
            
            If (Simulateur.Tisi.TxClavierD And &H1) = &H1 Then Lng = Lng Or &H1
            If (Simulateur.Tisi.TxClavierD And &H2) = &H2 Then Lng = Lng Or &H4
            If (Simulateur.Tisi.TxClavierD And &H4) = &H4 Then Lng = Lng Or &H2
            If (Simulateur.Tisi.TxClavierD And &H8) = &H8 Then Lng = Lng Or &H808
            
            ' Présence badge
            ' ==============
            ' Gauche
            If Simulateur.Tisi.TxBadgePresentG Then
                Lng = Lng Or &H2000
            End If
            ' Droite
            If Simulateur.Tisi.TxBadgePresentD Then
                Lng = Lng Or &H4000
            End If
            
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            
            
            
            
            ' Entrée TOR
            ' ==========
            Mot = 43
            ' REVERSE
            Lng = (Not Simulateur.Tisi.TxETOR) And &HFF&
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            
            ' Sortie TOR
            ' ==========
            Mot = 85
            ' REVERSE
            Lng = (Not Simulateur.Tisi.TxSTOR) And &HFF&
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
        
        End If
        
        ' CRC16
        ' =====
        ' longueur * 2 + 3 -1
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
        
    ElseIf (AdresseDebut = Simulateur.Tisi.Lecture3ModbusDebut) Then
        ' Lecture Compartimentage
        ' Dimensionnement de la trame
        i = Longueur * 2
        TxLen = 3 + i + 2
        ReDim TxBuffer(TxLen - 1)
        ' encodage Header
        ' ===============
        TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
        TxBuffer(1) = CByte(Fonction)
        TxBuffer(2) = CByte(Longueur * 2)
        
        ' Pour Recopie Intégrale des données
'        For x = 1 To 240
'            Simulateur.Tisi.TxEtendu(x) = Simulateur.Tisi.RxEtendu(x)
'            If Simulateur.Tisi.TxEtendu(x) = 255 Then
'                Simulateur.Tisi.TxEtendu(x) = 0
'            Else
'                Simulateur.Tisi.TxEtendu(x) = Simulateur.Tisi.TxEtendu(x) + 1
'            End If
'        Next x
'
'        For x = 1 To 240
'            TxBuffer(4 + x - 1) = Simulateur.Tisi.TxEtendu(x)
'        Next x

        Simulateur.Tisi.TxEtenduModeMarche = Simulateur.Tisi.RxEtenduModeMarche
        Simulateur.Tisi.TxEtenduTypeData = Simulateur.Tisi.RxEtenduTypeData
        Simulateur.Tisi.TxEtenduTotalRecord = Simulateur.Tisi.RxEtenduTotalRecord
        Simulateur.Tisi.TxEtenduFirstRecordBloc = Simulateur.Tisi.RxEtenduFirstRecordBloc
        Simulateur.Tisi.TxEtenduRecordQuantityBloc = Simulateur.Tisi.RxEtenduRecordQuantityBloc


        ' Mise à jour des données intessante
        TxBuffer(4 - 1) = Simulateur.Tisi.TxEtenduModeMarche
        TxBuffer(5 - 1) = Simulateur.Tisi.TxEtenduTypeData
        TxBuffer(6 - 1) = 0
        TxBuffer(7 - 1) = Simulateur.Tisi.TxEtenduTotalRecord
        TxBuffer(8 - 1) = Simulateur.Tisi.TxEtenduFirstRecordBloc
        TxBuffer(9 - 1) = Simulateur.Tisi.TxEtenduRecordQuantityBloc

    
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
        
        
    Else
        ' Erreur zone
        TxLen = 5
        ReDim TxBuffer(TxLen - 1)
        TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
        TxBuffer(1) = CByte(Fonction + 128)
        TxBuffer(2) = 2
        ' CRC16
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    End If
    
    
    Case 16     ' Ecriture de mots
    If (AdresseDebut = Simulateur.Tisi.Ecriture1ModbusDebut) Or (AdresseDebut = Simulateur.Tisi.Ecriture2ModbusDebut) Or (AdresseDebut = Simulateur.Tisi.Ecriture3ModbusDebut) Or (AdresseDebut = Simulateur.Tisi.Ecriture4ModbusDebut) Or (AdresseDebut = Simulateur.Tisi.Ecriture5ModbusDebut) Then
        TxLen = 8
        ReDim TxBuffer(TxLen - 1)
        ' encodage Header
        ' ===============
        TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
        TxBuffer(1) = CByte(Fonction)
        TxBuffer(2) = CByte((AdresseDebut And &HFF00&) / &H100)
        TxBuffer(3) = CByte(AdresseDebut And &HFF)
        
        TxBuffer(4) = CByte((Longueur And &HFF00&) / &H100)
        TxBuffer(5) = CByte(Longueur And &HFF)
        
        ' CRC16
        ' =====
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    ElseIf (AdresseDebut = Simulateur.Tisi.Ecriture6ModbusDebut) Then
        ' Compartimentage
        TxLen = 8
        ReDim TxBuffer(TxLen - 1)
        ' encodage Header
        ' ===============
        TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
        TxBuffer(1) = CByte(Fonction)
        TxBuffer(2) = CByte((AdresseDebut And &HFF00&) / &H100)
        TxBuffer(3) = CByte(AdresseDebut And &HFF)
        
        TxBuffer(4) = CByte((Longueur And &HFF00&) / &H100)
        TxBuffer(5) = CByte(Longueur And &HFF)
        
        
        ' CRC16
        ' =====
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    Else
        ' Erreur Zone
        TxLen = 5
        ReDim TxBuffer(TxLen - 1)
        TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
        TxBuffer(1) = CByte(Fonction + 128)
        TxBuffer(2) = 2
        ' crc16
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    End If
    

    Case Else   ' Fonction non supportée
    ' ==================================
    TxLen = 5
    ReDim TxBuffer(TxLen - 1)
    TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
    TxBuffer(1) = CByte(Fonction + 128)
    TxBuffer(2) = 1
    ' crc16
    Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    

End Select

MakeReponseTisi = TxLen
End Function

Public Function MakeReponseBras(TxBuffer() As Byte, Bras As Integer, Fonction As Integer, _
    AdresseDebut As Long, Longueur As Long) As Integer
' Construit la réponse
' ====================
Dim TxLen As Integer
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim Mot As Integer
Dim Lng As Long

Select Case Fonction
    Case 3, 4   ' Lecture de mots
        If AdresseDebut = Simulateur.Bras(Bras).LectureModbusDebut Then
            ' Dimensionnement de la trame
            i = Longueur * 2
            TxLen = 3 + i + 2
            ReDim TxBuffer(TxLen - 1)
            ' encodage Header
            ' ===============
            TxBuffer(0) = CByte(Simulateur.Bras(Bras).Numero)
            TxBuffer(1) = CByte(Fonction)
            TxBuffer(2) = CByte(Longueur * 2)
            ' Pas de données
            ' ==============
            
            
            Lng = 0
            If Simulateur.Bras(Bras).TxBrasBaisse Then Lng = Lng Or &H2
            If Simulateur.Bras(Bras).TxPasserelleD Then Lng = Lng Or &H4
            If Simulateur.Bras(Bras).TxPasserelleG Then Lng = Lng Or &H8
            If Simulateur.Bras(Bras).TxOrientationD Then Lng = Lng Or &H10
            If Simulateur.Bras(Bras).TxOrientationG Then Lng = Lng Or &H20
            If Simulateur.Bras(Bras).TxTerre Then Lng = Lng Or &H80
            If Simulateur.Bras(Bras).TxTerre Then Lng = Lng Or &H80
            If Simulateur.Bras(Bras).TxTerreD Then Lng = Lng Or &H40
            If Simulateur.Bras(Bras).TxBrasVapeur Then Lng = Lng Or &H100
            
            If Simulateur.Bras(Bras).TxChangementBE Then
                ' Monte le bit dans la Trame puis le repositionne le Flag à Zéro
                Lng = Lng Or &H400
                'Simulateur.Bras(Bras).TxChangementBE = False
            End If
            
            
            If Simulateur.Bras(Bras).TxDemandeProduit Then Lng = Lng Or &H800
            If Simulateur.Bras(Bras).TxSondeAPi Then Lng = Lng Or &H20
            
            If Simulateur.Bras(Bras).TxDemandeReleve Then Lng = Lng Or &H2000
            If Simulateur.Bras(Bras).TxPriseEnCompteCorrecte Then Lng = Lng Or &H4000
            
            ' Pour Forcage demande de releve
            If Simulateur.Bras(Bras).TxForcageDemandeReleve Then Lng = Lng Or &H2000
            If Simulateur.Bras(Bras).TxForcagePriseEnCompteCorrecte Then Lng = Lng Or &H4000
            
            
            
            ' Code defaut
            If Simulateur.Bras(Bras).TxCodeDefaut <> 0 Then Lng = Lng Or &H8000
            
            
            Mot = 1
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            
            Lng = 0
            If Simulateur.Bras(Bras).TxDemandeChargementD Then Lng = Lng Or &H100
            If Simulateur.Bras(Bras).TxDemandeChargement Then Lng = Lng Or &H200
            If Simulateur.Bras(Bras).TxAutonome Then Lng = Lng Or &H1000
            
            If Simulateur.Bras(Bras).TxPresenceTicket Then Lng = Lng Or &H8000
            
            Lng = Lng + (Simulateur.Bras(Bras).TxCodeDefaut)
            
    '        Debug.Print "Mot 2  H" & Hex$(Lng)
            
            Mot = 2
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            
            
            ' Mot n° 3 Volume
            Mot = 3
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Simulateur.Bras(Bras).TxVolume And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Simulateur.Bras(Bras).TxVolume And &HFF&))
            
            ' Mot n° 4 Fuite
            Mot = 4
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Simulateur.Bras(Bras).TXFuite And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Simulateur.Bras(Bras).TXFuite And &HFF&))
            ' Mot n° 5 Débit
            Mot = 5
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Simulateur.Bras(Bras).TxDebit And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Simulateur.Bras(Bras).TxDebit And &HFF&))
            
            ' Mot n° 6 T° ins
            Mot = 6
            Lng = CLng(Simulateur.Bras(Bras).TxTemperatureInstantannée * 10#)
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            ' Mot n° 7 T° Moy
            Mot = 7
            Lng = CLng(Simulateur.Bras(Bras).TxTemperatureMoyenne * 10#)
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            ' Recopie affichage
            Mot = 8
            TxBuffer(((Mot - 1) * 2) + 3) = Asc(Mid$(Simulateur.Bras(Bras).TxAffichage, 1, 1))
            TxBuffer(((Mot - 1) * 2) + 4) = Asc(Mid$(Simulateur.Bras(Bras).TxAffichage, 2, 1))
            TxBuffer(((Mot - 1) * 2) + 5) = Asc(Mid$(Simulateur.Bras(Bras).TxAffichage, 3, 1))
            TxBuffer(((Mot - 1) * 2) + 6) = Asc(Mid$(Simulateur.Bras(Bras).TxAffichage, 4, 1))
            TxBuffer(((Mot - 1) * 2) + 7) = Asc(Mid$(Simulateur.Bras(Bras).TxAffichage, 5, 1))
            TxBuffer(((Mot - 1) * 2) + 8) = Asc(Mid$(Simulateur.Bras(Bras).TxAffichage, 6, 1))
            TxBuffer(((Mot - 1) * 2) + 9) = Asc(Mid$(Simulateur.Bras(Bras).TxAffichage, 7, 1))
            TxBuffer(((Mot - 1) * 2) + 10) = Asc(Mid$(Simulateur.Bras(Bras).TxAffichage, 8, 1))
            TxBuffer(((Mot - 1) * 2) + 11) = Asc(Mid$(Simulateur.Bras(Bras).TxAffichage, 9, 1))
            TxBuffer(((Mot - 1) * 2) + 12) = Asc(Mid$(Simulateur.Bras(Bras).TxAffichage, 10, 1))
            
            
            ' Mot n° 13 Pression
            Mot = 13
            Lng = CLng(Simulateur.Bras(Bras).TxPression * 10#)
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            ' Injecteurs
            k = 0
            Select Case Simulateur.Bras(Bras).Modele
                Case V16_3_Injecteurs, V17_3_Injecteurs
                Mot = 15
                k = 3
            
                Case V8_3_Injecteurs, V9_3_Injecteurs, V10_3_Injecteurs, V13_3_Injecteurs
                Mot = 15
                k = 3
                
                Case V16_8_Injecteurs, V17_8_Injecteurs
                Mot = 15
                k = 8
                
                Case V20_8_Injecteurs
                Mot = 15
                k = 8
                
                
                Case V8_8_Injecteurs, V9_8_Injecteurs, V10_8_Injecteurs, V13_8_Injecteurs
                Mot = 15
                k = 8
                
            End Select
            
            ' Taux et Commande Injecteur
            ' ==========================
            If k > 0 Then
                For j = 1 To k
                    ' Pf Taux
                    TxBuffer(((Mot - 1) * 2) + 4) = CByte(Simulateur.Bras(Bras).Injecteur(j).TxTaux)
                    ' PF Dose
                    TxBuffer(((Mot - 1) * 2) + 3) = _
                        CByte(Simulateur.Bras(Bras).Injecteur(j).TrancheInjectee)
                    
                    Mot = Mot + 1
                Next j
            End If
            
            ' Injecteurs
            k = 0
            Select Case Simulateur.Bras(Bras).Modele
            
                Case V8_3_Injecteurs, V9_3_Injecteurs, V10_3_Injecteurs, V13_3_Injecteurs, _
                    V16_3_Injecteurs, V17_3_Injecteurs
                Mot = 17
                k = 3
                
                Case V8_8_Injecteurs, V9_8_Injecteurs, V10_8_Injecteurs, V13_8_Injecteurs, _
                    V16_8_Injecteurs, V17_8_Injecteurs
                Mot = 23
                k = 8
                
                Case V20_8_Injecteurs
                Mot = 23
                k = 8
                
            End Select
            
            ' Totalisateur Injecteur
            ' ======================
            If k > 0 Then
                For j = 1 To k
                    ' Totalisateur
                    Lng = Simulateur.Bras(Bras).Injecteur(j).TxTotalisateur
                    TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF000000) / &H1000000)
                    TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF0000) / &H10000)
                    Mot = Mot + 1
                    TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                    TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
                    Mot = Mot + 1
                Next j
            End If
            
                    
            ' Totalisateur
            Mot = Mot + 1
            ' Totalisateur
            Lng = Simulateur.Bras(Bras).TxTotalisateur
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF000000) / &H1000000)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF0000) / &H10000)
            Mot = Mot + 1
            TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
            TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            
            Select Case Simulateur.Bras(Bras).Modele
                Case V13_3_Injecteurs, V10_3_Injecteurs, V9_3_Injecteurs, V16_3_Injecteurs, _
                    V17_3_Injecteurs
                    'Lng = (Simulateur.Bras(Bras).TxInjecteurColorant * &H100)
                    'Lng = Lng + (Simulateur.Bras(Bras).TxInjecteurAdditif)
                    Mot = 29
                    Lng = 0
                    If Simulateur.Bras(Bras).TxCustomInput1 Then Lng = Lng Or 1
                    If Simulateur.Bras(Bras).TxCustomInput2 Then Lng = Lng Or 2
                    If Simulateur.Bras(Bras).TxPSL Then Lng = Lng Or 16
                    If Simulateur.Bras(Bras).TxDemandeAcquit Then Lng = Lng Or 32
                    Debug.Print "Mot 29  H" & Hex$(Lng)
                
                    TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                    TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
                
                    
                Case V13_8_Injecteurs, V10_8_Injecteurs, V9_8_Injecteurs, V16_8_Injecteurs, _
                    V17_8_Injecteurs, V20_8_Injecteurs
                    Mot = 44
                    Lng = 0
                    If Simulateur.Bras(Bras).TxCustomInput1 Then Lng = Lng Or 1
                    If Simulateur.Bras(Bras).TxCustomInput2 Then Lng = Lng Or 2
                    If Simulateur.Bras(Bras).TxPSL Then Lng = Lng Or 16
                    If Simulateur.Bras(Bras).TxDemandeAcquit Then Lng = Lng Or 32
                    If Simulateur.Bras(Bras).TxRecopiePD Then Lng = Lng Or &H4
                    If Simulateur.Bras(Bras).TxRecopieGD Then Lng = Lng Or &H8
                    
                    
                    Debug.Print "Mot 44  H" & Hex$(Lng)
                
                    TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                    TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            End Select
            
            
            
            Select Case Simulateur.Bras(Bras).Modele
                Case V13_3_Injecteurs, V16_3_Injecteurs, V17_3_Injecteurs
                Lng = (Simulateur.Bras(Bras).TxInjecteurColorant * &H100)
                Lng = Lng + (Simulateur.Bras(Bras).TxInjecteurAdditif)
                Mot = 34
                If Bras = 1 Then
                    Debug.Print "Extention injecteur " & Hex$(Lng)
                End If
            
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
                
                Case V13_8_Injecteurs, V16_8_Injecteurs, V17_8_Injecteurs, V20_8_Injecteurs
                Lng = (Simulateur.Bras(Bras).TxInjecteurColorant * &H100)
                Lng = Lng + (Simulateur.Bras(Bras).TxInjecteurAdditif)
                Mot = 49
            
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
            End Select
            
            
            ' Mot n° 43 tension vapeur
            Select Case Simulateur.Bras(Bras).Modele
                Case V13_8_Injecteurs, V10_8_Injecteurs, V9_8_Injecteurs, V16_8_Injecteurs, _
                    V17_8_Injecteurs, V20_8_Injecteurs
            
                Mot = 43
                Lng = CLng(Simulateur.Bras(Bras).TxTV * 10#)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
    
                Case V13_3_Injecteurs, V10_3_Injecteurs, V9_3_Injecteurs, V16_3_Injecteurs, _
                    V17_3_Injecteurs
            
                Mot = 28
                Lng = CLng(Simulateur.Bras(Bras).TxTV * 10#)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
    
            
            End Select
            
            ' Mot n° 45 Prédé saisie
            ' ======================
            Select Case Simulateur.Bras(Bras).Modele
                Case V13_8_Injecteurs, V10_8_Injecteurs, V9_8_Injecteurs, V16_8_Injecteurs, _
                    V17_8_Injecteurs, V20_8_Injecteurs
            
                Mot = 45
                Lng = CLng(Simulateur.Bras(Bras).TxPrede)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
    
                Case V13_3_Injecteurs, V10_3_Injecteurs, V9_3_Injecteurs, V16_3_Injecteurs, _
                    V17_3_Injecteurs
            
                Mot = 30
                Lng = CLng(Simulateur.Bras(Bras).TxPrede)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
    
            
            End Select
            
            
            ' Mot 50-35 - Identifiant Autorisation
            ' =================================
            Select Case Simulateur.Bras(Bras).Modele
                Case V16_8_Injecteurs, V17_8_Injecteurs, V20_8_Injecteurs
            
                Mot = 50    ' et 51
                Lng = CLng(Simulateur.Bras(Bras).TxIdentifiantAutorisation)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF000000) / &H1000000)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF0000) / &H10000)
                Mot = Mot + 1
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
    
                Case V16_3_Injecteurs, V17_3_Injecteurs
            
                Mot = 35    ' et 36
                Lng = CLng(Simulateur.Bras(Bras).TxIdentifiantAutorisation)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF000000) / &H1000000)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF0000) / &H10000)
                Mot = Mot + 1
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
    
            
            End Select
            
            ' Volume Additif et Colorant
            ' ==========================
            
            Simulateur.Bras(Bras).TxVolumeAdditif = 1000
            Simulateur.Bras(Bras).TxVolumeColorant = 2000
            
            Select Case Simulateur.Bras(Bras).Modele
                Case V17_8_Injecteurs, V20_8_Injecteurs
                
                Mot = 52   ' et 53 - 54-55
                ' Volume Additif
                
                
                Lng = CLng(Simulateur.Bras(Bras).TxVolumeAdditif)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF000000) / &H1000000)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF0000) / &H10000)
                Mot = Mot + 1
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
                
                
                
                
                ' Volume colorant
                Mot = 54   '
                Lng = CLng(Simulateur.Bras(Bras).TxVolumeColorant)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF000000) / &H1000000)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF0000) / &H10000)
                Mot = Mot + 1
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
                
                
            
                Case V17_3_Injecteurs
                Mot = 37   ' et 38 - 39-40
                ' Volume Additif
                Lng = CLng(Simulateur.Bras(Bras).TxVolumeAdditif)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF000000) / &H1000000)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF0000) / &H10000)
                Mot = Mot + 1
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
                
                
                ' Volume colorant
                Mot = 39   '
                Lng = CLng(Simulateur.Bras(Bras).TxVolumeColorant)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF000000) / &H1000000)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF0000) / &H10000)
                Mot = Mot + 1
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
                
                
            
            End Select
            
            Select Case Simulateur.Bras(Bras).Modele
                Case V20_8_Injecteurs
                ' Données Blending
                ' Totalisateur Général Blending
                Mot = 63    ' & 64
                Lng = Simulateur.Bras(Bras).TxBlendingTotalisateur
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF000000) / &H1000000)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF0000) / &H10000)
                Mot = Mot + 1
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
                
                ' Volume Courant Blending
                Mot = 65    ' & 66
                Lng = Simulateur.Bras(Bras).TxBlendingVolume * 10
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF000000) / &H1000000)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF0000) / &H10000)
                Mot = Mot + 1
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
                
                ' Taux Melange
                Mot = 67
                Lng = CLng(Simulateur.Bras(Bras).TxBlendingRate * 100#)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
                
                ' Taux Satisfaction Mélange
                Mot = 68
                ' NOT USED
                
                
                ' Température Instantannée
                Mot = 69
                Lng = CLng(Simulateur.Bras(Bras).TxBlendingTemperature * 10#)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
                
                
                ' Température Moyenne
                Mot = 70
                Lng = CLng(Simulateur.Bras(Bras).TxBlendingTemperatureMoyenne * 10#)
                TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
                TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
                
                
                
                
                Case Else
            
            End Select
            
            
            ' CRC16
            ' =====
            ' longueur * 2 + 3 -1
            Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
            
        Else
            ' Erreur zone
            TxLen = 5
            ReDim TxBuffer(TxLen - 1)
            TxBuffer(0) = CByte(Simulateur.Bras(Bras).Numero)
            TxBuffer(1) = CByte(Fonction + 128)
            TxBuffer(2) = 2
            ' CRC16
            Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
        End If
    
    
    Case 16     ' Ecriture de mots
        If AdresseDebut = Simulateur.Bras(Bras).EcritureModbusDebut Then
            TxLen = 8
            ReDim TxBuffer(TxLen - 1)
            ' encodage Header
            ' ===============
            TxBuffer(0) = CByte(Simulateur.Bras(Bras).Numero)
            TxBuffer(1) = CByte(Fonction)
            TxBuffer(2) = CByte((AdresseDebut And &HFF00&) / &H100)
            TxBuffer(3) = CByte(AdresseDebut And &HFF)
            
            TxBuffer(4) = CByte((Longueur And &HFF00&) / &H100)
            TxBuffer(5) = CByte(Longueur And &HFF)
            
            ' CRC16
            ' =====
            Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
        Else
            ' Erreur Zone
            TxLen = 5
            ReDim TxBuffer(TxLen - 1)
            TxBuffer(0) = CByte(Simulateur.Bras(Bras).Numero)
            TxBuffer(1) = CByte(Fonction + 128)
            TxBuffer(2) = 2
            ' crc16
            Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
        End If
    

    Case Else   ' Fonction non supportée
    ' ==================================
        TxLen = 5
        ReDim TxBuffer(TxLen - 1)
        TxBuffer(0) = CByte(Simulateur.Bras(Bras).Numero)
        TxBuffer(1) = CByte(Fonction + 128)
        TxBuffer(2) = 1
        ' crc16
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    

End Select

MakeReponseBras = TxLen

End Function

Public Sub DecodeBras(RxBuffer() As Byte, Bras As Integer, Fonction As Integer)
Dim Mot As Integer
Dim Lng As Long
Dim MessageBras As String
Dim FrameSize As Integer
On Error GoTo DecodeBrasErr



Select Case Fonction
    Case 16
    
    FrameSize = UBound(RxBuffer)
    ' On réduit FrameSize de 2 octets (CRC16)
    FrameSize = FrameSize - 2

    
    Mot = 1
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
    
        Lng = ((CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + CLng(RxBuffer(((Mot - 1) * 2) + 8)))
        If (Lng And &H4) = &H4 Then
            Simulateur.Bras(Bras).RxAutorisationCalculateur = True
        Else
            Simulateur.Bras(Bras).RxAutorisationCalculateur = False
        End If
        
        If (Lng And &H8) = &H8 Then
            Simulateur.Bras(Bras).RxAutorisationClient = True
        Else
            Simulateur.Bras(Bras).RxAutorisationClient = False
        End If
        
        If (Lng And &H40) = &H40 Then
            Simulateur.Bras(Bras).RxPriseEnCompteVolume = True
        Else
            Simulateur.Bras(Bras).RxPriseEnCompteVolume = False
        End If
        
        If (Lng And &H80) = &H80 Then
            Simulateur.Bras(Bras).RxVolumeReleve = True
        Else
            Simulateur.Bras(Bras).RxVolumeReleve = False
        End If
        
        'RxAcquit
        If (Lng And &H1) = &H1 Then
            Simulateur.Bras(Bras).RxAcquit = True
        Else
            Simulateur.Bras(Bras).RxAcquit = False
        End If
        'If Bras = 1 Then
            Debug.Print "Bras " & Bras & "  " & Hex$(Lng)
        'End If
        
        Simulateur.Bras(Bras).RxCodeDefaut = (((CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + _
            CLng(RxBuffer(((Mot - 1) * 2) + 8))) And &HFF00) / &H100
    
    End If
    ' Code Produit PF Mot n°2
    Mot = 2
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
            ' Code Produit PF Mot n°2
        Simulateur.Bras(Bras).RxProduit = CLng(RxBuffer(((Mot - 1) * 2) + 8)) And &HFF
        ' Additif
        Simulateur.Bras(Bras).RxAdditif = CLng(RxBuffer(((Mot - 1) * 2) + 7)) And &HF
        ' Colorant
        Simulateur.Bras(Bras).RxColorant = (CLng(RxBuffer(((Mot - 1) * 2) + 7)) And &HF0) / &H10
    End If
    ' Quota mot n° 3
    Mot = 3
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
        Simulateur.Bras(Bras).RxQuota = (CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + _
            CLng(RxBuffer(((Mot - 1) * 2) + 8))
    End If
    
    ' Déjà chargée Mot n° 4
    Mot = 4
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
        Simulateur.Bras(Bras).RxDejaChargee = (CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + _
            CLng(RxBuffer(((Mot - 1) * 2) + 8))
    End If
    ' Température déjà chargée Mot n° 5
    Mot = 5
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
        Simulateur.Bras(Bras).RxTemperatureDejaChargee = CSng((CLng(RxBuffer(((Mot - 1) * 2) + 7)) * _
            &H100&) + CLng(RxBuffer(((Mot - 1) * 2) + 8))) / 10#
    End If
    
    ' Affichage bras
    ' ==============
    MessageBras = ""
    For Mot = 6 To 10
        If FrameSize >= (((Mot - 1) * 2) + 8) Then
            MessageBras = MessageBras & Chr$(RxBuffer(((Mot - 1) * 2) + 7))
            MessageBras = MessageBras & Chr$(RxBuffer(((Mot - 1) * 2) + 8))
        End If
    Next Mot

    Simulateur.Bras(Bras).RxLibelleDefaut = MessageBras
    
    ' Volume de controle Mot N°11
    ' ===========================
    Mot = 11
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
        Simulateur.Bras(Bras).RxVolumeControle = (CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + _
            CLng(RxBuffer(((Mot - 1) * 2) + 8))
    End If
    
    
    
    Mot = 13
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
    
        Lng = ((CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + CLng(RxBuffer(((Mot - 1) * 2) + 8)))
        If (Lng And &H4000) = &H4000 Then
            Simulateur.Bras(Bras).RxPresenceSondeCamion = True
        Else
            Simulateur.Bras(Bras).RxPresenceSondeCamion = False
        End If
        
        If (Lng And &H100) = &H100 Then
            Simulateur.Bras(Bras).RxCustomOutPut1 = True
        Else
            Simulateur.Bras(Bras).RxCustomOutPut1 = False
        End If
        
        If (Lng And &H200) = &H200 Then
            Simulateur.Bras(Bras).RxCustomOutPut2 = True
        Else
            Simulateur.Bras(Bras).RxCustomOutPut2 = False
        End If
        
        
    End If
    
    
    Mot = 20
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
        ' N° Autorisation Chargement
        ' ==========================
        Mot = 19
        
        Lng = (CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + CLng(RxBuffer(((Mot - 1) * 2) + 8))
        Lng = Lng * &H10000
        Mot = Mot + 1
        Lng = Lng + (CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + CLng(RxBuffer(((Mot - 1) * 2) + _
            8))
        
        Simulateur.Bras(Bras).RxIdentifiantAutorisation = Lng
                
        'If Simulateur.Bras(Bras).RxIdentifiantAutorisation <> Simulateur.Bras(Bras).TxIdentifiantAutorisation Then
            ' Raz de la demande de changement de BE
            'Simulateur.Bras(Bras).TxChangementBE = False
            'Simulateur.Bras(Bras).TxIdentifiantAutorisation = Simulateur.Bras(Bras).RxIdentifiantAutorisation
        'End If
        
        If Simulateur.Bras(Bras).ChangementBEEnCours Then
            If Simulateur.Bras(Bras).RxIdentifiantAutorisation <> Simulateur.Bras(Bras).MemoIDBe Then
                Simulateur.Bras(Bras).TxChangementBE = False
                Simulateur.Bras(Bras).ChangementBEEnCours = False
                'Simulateur.Bras(Bras).TxIdentifiantAutorisation = Simulateur.Bras(Bras).RxIdentifiantAutorisation
            End If
            'Simulateur.Bras(Bras).TxIdentifiantAutorisation = Simulateur.Bras(Bras).RxIdentifiantAutorisation
        End If
        
        
        Simulateur.Bras(Bras).TxIdentifiantAutorisation = _
            Simulateur.Bras(Bras).RxIdentifiantAutorisation
    End If
    
    ' Libelle produit / Additif / Colorant
    Mot = 29
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
        MessageBras = ""
        For Mot = 21 To 23
            If FrameSize >= (((Mot - 1) * 2) + 8) Then
                MessageBras = MessageBras & Chr$(RxBuffer(((Mot - 1) * 2) + 7))
                MessageBras = MessageBras & Chr$(RxBuffer(((Mot - 1) * 2) + 8))
            End If
        Next Mot
    
        Simulateur.Bras(Bras).RxLibelleProduit = MessageBras
        
        MessageBras = ""
        For Mot = 24 To 26
            If FrameSize >= (((Mot - 1) * 2) + 8) Then
                MessageBras = MessageBras & Chr$(RxBuffer(((Mot - 1) * 2) + 7))
                MessageBras = MessageBras & Chr$(RxBuffer(((Mot - 1) * 2) + 8))
            End If
        Next Mot
    
        Simulateur.Bras(Bras).RxLibelleAdditif = MessageBras
        
        MessageBras = ""
        For Mot = 27 To 29
            If FrameSize >= (((Mot - 1) * 2) + 8) Then
                MessageBras = MessageBras & Chr$(RxBuffer(((Mot - 1) * 2) + 7))
                MessageBras = MessageBras & Chr$(RxBuffer(((Mot - 1) * 2) + 8))
            End If
        Next Mot
    
        Simulateur.Bras(Bras).RxLibelleColorant = MessageBras
        
    End If
    
    ' PPM DEMANDE
    Mot = 30
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
        Simulateur.Bras(Bras).RxPPMAdditif = CSng((CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + _
            CLng(RxBuffer(((Mot - 1) * 2) + 8))) / 1000#
    End If
    Mot = 31
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
        Simulateur.Bras(Bras).RxPPMColorant = CSng((CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + _
            CLng(RxBuffer(((Mot - 1) * 2) + 8))) / 1000#
    End If
    
    
    ' Ordre Melange
    Mot = 33
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
        Simulateur.Bras(Bras).RxBlendingRun = (CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + _
            CLng(RxBuffer(((Mot - 1) * 2) + 8))
    End If
    ' Taux Melange
    Mot = 34
    If FrameSize >= (((Mot - 1) * 2) + 8) Then
        Simulateur.Bras(Bras).RxBlendingRate = (CLng(RxBuffer(((Mot - 1) * 2) + 7)) * &H100&) + _
            CLng(RxBuffer(((Mot - 1) * 2) + 8))
    End If
    
    
    
    Case Else
    
    
End Select

Exit Sub

DecodeBrasErr:
Debug.Print "DecodeBras Erreur : " & Err.Number & " " & Err.Description

End Sub

Public Sub DecodeTisi(RxBuffer() As Byte, Fonction As Integer, Adresse As Long)
Dim FrameSize As Integer
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim x As Integer
Dim Mot As Integer
Dim HighByte As Byte
Dim LowByte As Byte

Select Case Fonction
    Case 16
    
    FrameSize = UBound(RxBuffer)
    
    'Debug.Print "Decodage Tisi : Fonction " & Fonction & " Adresse " & Adresse & " RxSize " & FrameSize
    
    If Adresse = 0 Then
        ' Ecran
    
        k = 11
        For i = 1 To 5
            Simulateur.Tisi.RxAffichage(i) = ""
            For j = 1 To 16
                If k <= FrameSize Then
                    Mid$(Simulateur.Tisi.RxAffichage(i), j, 1) = Chr$(RxBuffer(k))
                End If
                k = k + 1
            Next j
            'Debug.Print Simulateur.Tisi.RxAffichage(i)
        Next i
    
    ElseIf Adresse = 122 Then
        ' Sortie
        If FrameSize > 8 Then
            Simulateur.Tisi.RxSortie(1) = IIf((RxBuffer(8) And &H1) = &H1, True, False)
            Simulateur.Tisi.RxSortie(2) = IIf((RxBuffer(8) And &H2) = &H2, True, False)
            Simulateur.Tisi.RxSortie(3) = IIf((RxBuffer(8) And &H4) = &H4, True, False)
            Simulateur.Tisi.RxSortie(4) = IIf((RxBuffer(8) And &H8) = &H8, True, False)
        End If
    ElseIf Adresse = 127 Then
        ' Bits
        If FrameSize > 8 Then
            Simulateur.Tisi.RxBits(1) = IIf((RxBuffer(8) And &H1) = &H1, True, False)
            Simulateur.Tisi.RxBits(2) = IIf((RxBuffer(8) And &H2) = &H2, True, False)
            Simulateur.Tisi.RxBits(3) = IIf((RxBuffer(8) And &H4) = &H4, True, False)
            Simulateur.Tisi.RxBits(4) = IIf((RxBuffer(8) And &H8) = &H8, True, False)
        End If
    ElseIf Adresse = &H600 Then
        ' Ecriture Compartimentage
        For x = 1 To 240
            If (8 + x - 1) < UBound(RxBuffer) Then
                Simulateur.Tisi.RxEtendu(x) = RxBuffer(8 + x - 1)
            End If
        Next x
        
        ' Mot N° 1 (PF : Mode Marche - pf : Type Données)
        Mot = 1
        LowByte = CLng(RxBuffer(((Mot - 1) * 2) + 8)) And &HFF
        HighByte = CLng(RxBuffer(((Mot - 1) * 2) + 7)) And &HFF
        Simulateur.Tisi.RxEtenduModeMarche = HighByte
        Simulateur.Tisi.RxEtenduTypeData = LowByte
        ' Mot N°14 (PF : Code Langue - pf : Numéro de Quai)
        Mot = 14
        LowByte = CLng(RxBuffer(((Mot - 1) * 2) + 8)) And &HFF
        HighByte = CLng(RxBuffer(((Mot - 1) * 2) + 7)) And &HFF
        Simulateur.Tisi.RxEtenduCodeLangue = HighByte
        Simulateur.Tisi.RxEtenduNumeroQuai = LowByte
        ' Mot N°15 (pf : Nombre total d'enregistrement)
        Mot = 15
        LowByte = CLng(RxBuffer(((Mot - 1) * 2) + 8)) And &HFF
        HighByte = CLng(RxBuffer(((Mot - 1) * 2) + 7)) And &HFF
        Simulateur.Tisi.RxEtenduTotalRecord = LowByte
        ' Mot N°16 (PF : Numéro premier enregistrement du Bloc de données - pf : Nombre d'enregistrement dans le bloc)
        Mot = 16
        LowByte = CLng(RxBuffer(((Mot - 1) * 2) + 8)) And &HFF
        HighByte = CLng(RxBuffer(((Mot - 1) * 2) + 7)) And &HFF
        Simulateur.Tisi.RxEtenduFirstRecordBloc = HighByte
        Simulateur.Tisi.RxEtenduRecordQuantityBloc = LowByte
        
        
    End If
    
    Case Else
End Select

End Sub

Public Sub SaveConfig()
Dim Item As TIniSetItem
Dim i As Integer

Item.FileName = "Config.Ini"
Item.PathName = ""

' Paramètres de la liaison
Item.Section = "Liaison"

Item.Key = "Port"
Item.StringValue = Str$(Simulateur.Liaison.Port)
IniSetString Item

' Paramètres du tisi
Item.Section = "Tisi"
Item.Key = "Abonne"
Item.StringValue = Str$(Simulateur.Tisi.Numero)
IniSetString Item

Item.Key = "Disponible"
Item.StringValue = IIf(Simulateur.Tisi.Disponible, "1", "0")
IniSetString Item

' Parametre du pont
Item.Section = "Pont"
Item.Key = "Abonne"
Item.StringValue = Str$(Simulateur.Pont.Numero)
IniSetString Item

Item.Key = "Disponible"
Item.StringValue = IIf(Simulateur.Pont.Disponible, "1", "0")
IniSetString Item


' Paramètres des microcompt
For i = 1 To MAX_BRAS
    
    Item.Section = "Microcompt_" & Format$(i, "00")
    Item.Key = "Abonne"
    Item.StringValue = Str$(Simulateur.Bras(i).Numero)
    IniSetString Item
    
    Item.Key = "Type"
    Item.StringValue = Str$(Simulateur.Bras(i).Modele)
    IniSetString Item
    
    Item.Key = "Disponible"
    Item.StringValue = IIf(Simulateur.Bras(i).Disponible, "1", "0")
    IniSetString Item

Next i


' Paramètre pas défaut
Item.Section = "Valeurs"
Item.Key = "Débit"
Item.StringValue = Str$(Simulateur.ValeurParDefaut.Debit)
IniSetString Item

Item.Key = "Pression"
Item.StringValue = Str$(Simulateur.ValeurParDefaut.Pression)
IniSetString Item

Item.Key = "Prédé"
Item.StringValue = Str$(Simulateur.ValeurParDefaut.Prede)
IniSetString Item

Item.Key = "Température"
Item.StringValue = Str$(Simulateur.ValeurParDefaut.Temperature)
IniSetString Item


End Sub

Public Sub LoadConfig()

Dim Item As TIniGetItem
Dim i As Integer

Item.FileName = "Config.Ini"
Item.PathName = ""

' Paramètres de la liaison
Item.Section = "Liaison"
Item.Key = "Port"

IniGetString Item
If Item.Available And Item.PrmOk Then
    Simulateur.Liaison.Port = Val(Left$(Item.StringValue, Item.StringLen))
End If


' Paramètres du tisi
Item.Section = "Tisi"

Item.Key = "Abonne"
IniGetString Item
If Item.Available And Item.PrmOk Then
    Simulateur.Tisi.Numero = Val(Left$(Item.StringValue, Item.StringLen))
End If

Item.Key = "Disponible"
IniGetString Item
If Item.Available And Item.PrmOk Then
    Simulateur.Tisi.Disponible = IIf(Val(Left$(Item.StringValue, Item.StringLen)) = 1, True, False)
End If

' Paramètres du pont
Item.Section = "Pont"

Item.Key = "Abonne"
IniGetString Item
If Item.Available And Item.PrmOk Then
    Simulateur.Pont.Numero = Val(Left$(Item.StringValue, Item.StringLen))
End If

Item.Key = "Disponible"
IniGetString Item
If Item.Available And Item.PrmOk Then
    Simulateur.Pont.Disponible = IIf(Val(Left$(Item.StringValue, Item.StringLen)) = 1, True, False)
End If

' Paramètres des microcompt
For i = 1 To MAX_BRAS
    
    Item.Section = "Microcompt_" & Format$(i, "00")
    
    Item.Key = "Abonne"
    IniGetString Item
    If Item.Available And Item.PrmOk Then
        Simulateur.Bras(i).Numero = Val(Left$(Item.StringValue, Item.StringLen))
    End If
    
    Item.Key = "Type"
    IniGetString Item
    If Item.Available And Item.PrmOk Then
        Simulateur.Bras(i).Modele = Val(Left$(Item.StringValue, Item.StringLen))
    End If
    
    Item.Key = "Disponible"
    IniGetString Item
    If Item.Available And Item.PrmOk Then
        Simulateur.Bras(i).Disponible = IIf(Val(Left$(Item.StringValue, Item.StringLen)) = 1, True, False)
    End If

Next i

' Paramètre pas défaut
Item.Section = "Valeurs"

Item.Key = "Débit"
IniGetString Item
If Item.Available And Item.PrmOk Then
    Simulateur.ValeurParDefaut.Debit = Val(Left$(Item.StringValue, Item.StringLen))
End If

Item.Key = "Pression"
IniGetString Item
If Item.Available And Item.PrmOk Then
    Simulateur.ValeurParDefaut.Pression = Val(Left$(Item.StringValue, Item.StringLen))
End If

Item.Key = "Prédé"
IniGetString Item
If Item.Available And Item.PrmOk Then
    Simulateur.ValeurParDefaut.Prede = Val(Left$(Item.StringValue, Item.StringLen))
End If

Item.Key = "Température"
IniGetString Item
If Item.Available And Item.PrmOk Then
    Simulateur.ValeurParDefaut.Temperature = Val(Left$(Item.StringValue, Item.StringLen))
End If


End Sub

Public Sub DecodePont(RxBuffer() As Byte, Fonction As Integer, Adresse As Long)
Dim FrameSize As Integer
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim x As Integer
Dim Mot As Integer
Dim HighByte As Byte
Dim LowByte As Byte
Dim LongValue As Long

Select Case Fonction
    Case 16
    
    FrameSize = UBound(RxBuffer)
    
    'Debug.Print "Decodage Tisi : Fonction " & Fonction & " Adresse " & Adresse & " RxSize " & FrameSize
    
    If Adresse = 15 Then
        ' N° de VOie
        ' On ne traite pas
        Mot = 1
        LowByte = CLng(RxBuffer(((Mot - 1) * 2) + 8)) And &HFF
        HighByte = CLng(RxBuffer(((Mot - 1) * 2) + 7)) And &HFF
        LongValue = (CLng(HighByte) * &H100) + CLng(LowByte)
        
    ElseIf Adresse = 171 Then
        ' N° de Commande
        ' Mot N° 1 (PF : Mode Marche - pf : Type Données)
        Mot = 1
        LowByte = CLng(RxBuffer(((Mot - 1) * 2) + 8)) And &HFF
        HighByte = CLng(RxBuffer(((Mot - 1) * 2) + 7)) And &HFF
        LongValue = (CLng(HighByte) * &H100) + CLng(LowByte)
        If LongValue <> Simulateur.Pont.CodeCommande Then
            If LongValue = 19712 Then
                ' N° DSD +1
                Simulateur.Pont.NumeroDSD = Simulateur.Pont.NumeroDSD + 1
            End If
            Simulateur.Pont.CodeCommande = LongValue
        End If
    End If
    
    Case Else
End Select

End Sub

Public Function MakeReponsePont(TxBuffer() As Byte, Fonction As Integer, AdresseDebut As Long, Longueur As Long) As Integer
' Construit la réponse
' ====================
Dim TxLen As Integer
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim x As Integer
Dim Lng As Long
Dim Mot As Integer
Select Case Fonction
    Case 3, 4   ' Lecture de mots
    If (AdresseDebut = Simulateur.Pont.Lecture1ModbusDebut) Then
        ' Data
        ' Dimensionnement de la trame
        i = Longueur * 2
        TxLen = 3 + i + 2
        ReDim TxBuffer(TxLen - 1)
        ' encodage Header
        ' ===============
        TxBuffer(0) = CByte(Simulateur.Pont.Numero)
        TxBuffer(1) = CByte(Fonction)
        TxBuffer(2) = CByte(Longueur * 2)
        
        
        Mot = 4
        ' Masse courant
 '       Simulateur.Pont.Masse = &H100
        Lng = Simulateur.Pont.Masse
        TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
        TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
        
        
        Mot = 9
        ' Status
        Lng = 0 + 2
        TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
        TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
        
        
        Mot = 82
        ' Masse Transaction
        Lng = Simulateur.Pont.Masse
        TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
        TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
        
        Mot = 109
        ' N° DSD
        Lng = Simulateur.Pont.NumeroDSD
        TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
        TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
            
        ' CRC16
        ' =====
        ' longueur * 2 + 3 -1
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    ElseIf (AdresseDebut = Simulateur.Pont.Lecture2ModbusDebut) Then
        ' Feed Back
        ' Dimensionnement de la trame
        i = Longueur * 2
        TxLen = 3 + i + 2
        ReDim TxBuffer(TxLen - 1)
        ' encodage Header
        ' ===============
        TxBuffer(0) = CByte(Simulateur.Pont.Numero)
        TxBuffer(1) = CByte(Fonction)
        TxBuffer(2) = CByte(Longueur * 2)
        
        Mot = 1
        ' Commande en cours
'        Simulateur.Pont.CodeCommande = 1
        Lng = Simulateur.Pont.CodeCommande
        TxBuffer(((Mot - 1) * 2) + 3) = CByte((Lng And &HFF00&) / &H100)
        TxBuffer(((Mot - 1) * 2) + 4) = CByte((Lng And &HFF&))
        
        
        ' CRC16
        ' =====
        ' longueur * 2 + 3 -1
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    Else
        ' Erreur zone
        TxLen = 5
        ReDim TxBuffer(TxLen - 1)
        TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
        TxBuffer(1) = CByte(Fonction + 128)
        TxBuffer(2) = 2
        ' CRC16
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    End If
    
    
    Case 16     ' Ecriture de mots
    If (AdresseDebut = Simulateur.Pont.Ecriture1ModbusDebut) Or (AdresseDebut = Simulateur.Pont.Ecriture2ModbusDebut) Then
        TxLen = 8
        ReDim TxBuffer(TxLen - 1)
        ' encodage Header
        ' ===============
        TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
        TxBuffer(1) = CByte(Fonction)
        TxBuffer(2) = CByte((AdresseDebut And &HFF00&) / &H100)
        TxBuffer(3) = CByte(AdresseDebut And &HFF)
        
        TxBuffer(4) = CByte((Longueur And &HFF00&) / &H100)
        TxBuffer(5) = CByte(Longueur And &HFF)
        
        ' CRC16
        ' =====
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    ElseIf (AdresseDebut = Simulateur.Tisi.Ecriture6ModbusDebut) Then
        ' Compartimentage
        TxLen = 8
        ReDim TxBuffer(TxLen - 1)
        ' encodage Header
        ' ===============
        TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
        TxBuffer(1) = CByte(Fonction)
        TxBuffer(2) = CByte((AdresseDebut And &HFF00&) / &H100)
        TxBuffer(3) = CByte(AdresseDebut And &HFF)
        
        TxBuffer(4) = CByte((Longueur And &HFF00&) / &H100)
        TxBuffer(5) = CByte(Longueur And &HFF)
        
        
        ' CRC16
        ' =====
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    Else
        ' Erreur Zone
        TxLen = 5
        ReDim TxBuffer(TxLen - 1)
        TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
        TxBuffer(1) = CByte(Fonction + 128)
        TxBuffer(2) = 2
        ' crc16
        Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    End If
    

    Case Else   ' Fonction non supportée
    ' ==================================
    TxLen = 5
    ReDim TxBuffer(TxLen - 1)
    TxBuffer(0) = CByte(Simulateur.Tisi.Numero)
    TxBuffer(1) = CByte(Fonction + 128)
    TxBuffer(2) = 1
    ' crc16
    Call ProtocoleModbusBuildAndAddCRC16(TxBuffer(), TxLen - 1)
    

End Select

MakeReponsePont = TxLen
End Function
