using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace arinc_1553_CSharpGUI
{
    using U64BIT = System.UInt64;
    using U32BIT = System.UInt32;
    using U16BIT = System.UInt16;
    using U8BIT = System.Byte;
    using S64BIT = System.Int64;
    using S32BIT = System.Int32;
    using S16BIT = System.Int16;
    using S8BIT = System.SByte;

    /* Global (used for all modes) Message Structure for decoded 1553 msgs */
    public struct MSGSTRUCT
    {
        public U16BIT wType;               /* Contains the msg type (see above) */
        public U16BIT wBlkSts;             /* Contains the block status word */
        public U16BIT wTimeTag;            /* Time tag of message */
        public U16BIT wCmdWrd1;            /* First command word */
        public U16BIT wCmdWrd2;            /* Second command word (RT to RT) */
        public U16BIT wCmdWrd1Flg;         /* Is command word 1 valid? */
        public U16BIT wCmdWrd2Flg;         /* Is command word 2 valid? */
        public U16BIT wStsWrd1;            /* First status word */
        public U16BIT wStsWrd2;            /* Second status word */
        public U16BIT wStsWrd1Flg;         /* Is status word 1 valid? */
        public U16BIT wStsWrd2Flg;         /* Is status word 2 valid? */
        public U16BIT wWordCount;          /* Number of valid data words */

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
        public U16BIT[] aDataWrds;       /* An array of data words */

        /* The following are only applicable in BC mode */
        public U16BIT wBCCtrlWrd;          /* Contains the BC control word */
        public U16BIT wBCGapTime;          /* Message gap time word */
        public U16BIT wBCLoopBack1;        /* First looped back word */
        public U16BIT wTimeTag2;           /* wBCLoopBack2 is redefined as TimeTag2 */
        public U16BIT wBCLoopBack1Flg;     /* Is loop back 1 valid? */
        public U16BIT wTimeTag3;           /* wBCLoopBack2Flg is redefined as TimeTag3 */
    }

    public struct WordInfo
    {
        public string wordName;
        public U8BIT numOfParameters;
    }

    public struct CountValue
    {
        public U16BIT countValueU16Bit;
        public U32BIT countValueU32Bit;
    }

    public class Msg1553
    {
        /* Msg ID (and so also the data block ID) for this message */
        public short msgID;
        public string name;

        /* The duration at which this message is to be repeatedly transmitted */
        //public ushort frequency;

        /* The first minor frame of the major frame in which this message will appear */
        //public U8BIT startMnFrame;

        /* 1553 message type, e.g. BC->RT */
        public string type;
        public string channel;

        /* RT address, Sub Address and Word Count (or Mode Code) and the hex value of the CMD Word */
        public ushort rtAddr1;
        public ushort sa1;
        public ushort wordCount_ModeCode;
        public U16BIT cw1;

        /* Transmitting RT address, Sub Address and Word Count if this is a RT-RT message and the hex value of the CMD Word */
        public ushort rtAddr2;
        public ushort sa2;
        public U16BIT cw2;

        /* Bus A or B */
        public string bus;

        /* Whether retry is enabled on this message or not */
        public bool retryEnabled;

        /* If the retry should be on same or alternative bus */
        //public string retryType;

        /* Whether this is a time broadcast message */
        public bool isTimeBcst;

        /* User friendly names for the data words */
        public WordInfo[] wordInfo = new WordInfo[32];

        /* List of engg unit parameters in this message */
        public List<EguParameter> eguParams = new List<EguParameter>();   // doubt

        /* flag to tell if this message is to be logged */
        //public bool isLoggingEnabled = false;

        /* The MSGSTRUCT object last received from the 1553 controller for this message */
        MSGSTRUCT msgRunTimeData = new MSGSTRUCT();

        ulong combinedTT = 0;

        ushort timeTagResolution = 4;

        /* define DDC SDK constants */
        public const U16BIT ACE_ACCESS_CARD = 0;
        public const U16BIT ACE_MODE_BC = 0x0001;
        public const U16BIT ACE_BCCTRL_CHL_A = 0x0080;
        public const U16BIT ACE_BCCTRL_CHL_B = 0x0000;
        public const U16BIT ACE_BCCTRL_RETRY_ENA = 0x0100;
        public const U16BIT ACE_RETRY_ONCE = 1;
        public const U16BIT ACE_RETRY_ALT = 1;
        public const U16BIT ACE_OPCODE_XEQ = 0x0001;
        public const U16BIT ACE_CNDTST_ALWAYS = 0x000F;
        public const U16BIT ACE_OPCODE_CAL = 0x0003;
        public const U16BIT ACE_FRAME_MINOR = 0x0002;
        public const U16BIT ACE_FRAME_MAJOR = 0x0000;
        public const U16BIT ACE_BC_BSW_CHNL = 0x2000;
        public const U16BIT ACE_BCCTRL_RT_TO_RT = 0x0001;
        public const U16BIT ACE_BC_MSGLOC_NEXT_PURGE = 0;
        public const U16BIT ACE_MSG_RTTOBC = 1;
        public const U16BIT ACE_BC_BSW_ERRFLG = 0x1000;


        public void AddNewEguParameter(EguParameter param)
        {
            /* Create a new EguParameter object, fill it with values from the param argument and add to the list */
            EguParameter newParam = new EguParameter();
            newParam = param;
            eguParams.Add(newParam);
        }

        /* Returns a pointer to the EguParameter object with name "paraName" if found, else returns nullptr */
        public EguParameter GetParameter(string paraName)
        {
            foreach (EguParameter eguParam in eguParams)
            {
                if (eguParam.name == paraName)
                {
                    return eguParam;
                }
            }

            //qDebug() << __FUNCTION__ << "No parameter found with name " << paraName << " in message " << name;
            return null;
        }

        public void setMsgRuntimeData(MSGSTRUCT msgStruct)
        {
            /* For a BC<-RT message, if BSW indicates an error, then we do not want to update the data words. This is to
             * ensure old data is displayed in MessageDisplay even when the UUT is switched OFF. This is a requirement
             * provided by L&T. */
            if ((msgStruct.wType == ACE_MSG_RTTOBC) && ((msgStruct.wBlkSts & ACE_BC_BSW_ERRFLG) != 0))
            {
                // retain old data
                //memcpy(msgStruct.aDataWrds, msgRunTimeData.aDataWrds, sizeof(msgStruct.aDataWrds));
                Array.Copy(msgRunTimeData.aDataWrds, 0, msgStruct.aDataWrds, 0, msgStruct.aDataWrds.Length);
            }

            // Consume new run time data
            msgRunTimeData = msgStruct;

            // Compute the 48-bit time tag
            U64BIT temp1 = msgRunTimeData.wTimeTag + (ulong)msgRunTimeData.wTimeTag2 * 0x10000;
            U64BIT temp2 = (ulong)msgRunTimeData.wTimeTag3 * 0xFFFFFFFF;
            combinedTT = (ulong)((temp1 + temp2) * timeTagResolution);

            //qDebug() << __FUNCTION__ << "wTimeTag: " << QString::number(msgRunTimeData.wTimeTag) << ", wTimeTag2: " << QString::number(msgRunTimeData.wTimeTag2) << ", combinedTT: " << QString::number(combinedTT);
        }

        public MSGSTRUCT getMsgRunTimeData()
        {
            return msgRunTimeData;
        }

        public Msg1553()
        {
            // Reset
            ResetRunTimeData();
        }

        /* Copy constructor */
        public Msg1553(ref Msg1553 msg)
        {
            CopyObject(ref msg);
        }

        void CopyObject(ref Msg1553 msg)
        {
            // Reset
            ResetRunTimeData();

            msgID = msg.msgID;
            name = msg.name;
            //frequency = msg.frequency;
            //startMnFrame = msg.startMnFrame;
            type = msg.type;
            rtAddr1 = msg.rtAddr1;
            sa1 = msg.sa1;
            wordCount_ModeCode = msg.wordCount_ModeCode;
            cw1 = msg.cw1;
            rtAddr2 = msg.rtAddr2;
            sa2 = msg.sa2;
            cw2 = msg.cw2;
            bus = msg.bus;
            retryEnabled = msg.retryEnabled;
            //retryType = msg.retryType;
            isTimeBcst = msg.isTimeBcst;
            setMsgRuntimeData(msg.msgRunTimeData);

            //isLoggingEnabled = msg.isLoggingEnabled;

            for(int i = 0; i<32; i++)
            {
                wordInfo[i] = msg.wordInfo[i];
            }

            foreach (EguParameter e in msg.eguParams)
            {
                AddNewEguParameter(e);
            }
        }

        /* "=" operator */
        /*        Msg1553& Msg1553::operator=(const Msg1553& msg)
                {
                    CopyObject(msg);
                    return *this;
                }*/

        ~Msg1553()
        {
            /* Clean up all the dynamically created EguParameter objects */
            for (int i = 0; i < eguParams.Count; i++)
            {
                /* Delete the dynamically created object */
/*                if (eguParams[i] != null)
                    delete eguParams[i];*/

                /* Remove it from the list */
                eguParams.RemoveAt(i);
            }
        }

        ushort ReverseBitsUShort(ushort x)
        {
            x = (ushort)(((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1));
            x = (ushort)(((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2));
            x = (ushort)(((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4));
            x = (ushort)((x << 8) | (x >> 8));
            return x;
        }

        U32BIT ReverseBitsU32BIT(U32BIT n)
        {
            n = (n >> 1) & 0x55555555 | (n << 1) & 0xAAAAAAAA;
            n = (n >> 2) & 0x33333333 | (n << 2) & 0xCCCCCCCC;
            n = (n >> 4) & 0x0F0F0F0F | (n << 4) & 0xF0F0F0F0;
            n = (n >> 8) & 0x00FF00FF | (n << 8) & 0xFF00FF00;
            n = (n >> 16) | (n << 16);
            return n;
        }

        bool DoEguConversionForParam(ref EguParameter eguParam, List<CodedType> codedTypes)
        {
            CountValue countValueStr = new CountValue();

            /* Extract only the bits corresponding to this parameter */
            if (eguParam.length > 16)
            {
                //countValueStr.countValueU32Bit = (U32BIT) (msgRunTimeData.aDataWrds[eguParam.startWord] | msgRunTimeData.aDataWrds[eguParam.startWord + 1]);
                //countValueStr.countValueU32Bit = (U32BIT) (countValueStr.countValueU32Bit >> (int)eguParam.startBit);
                //U32BIT mask = (U32BIT) (0xFFFFFFFF >> (int)(32 - eguParam.length));
                //countValueStr.countValueU32Bit &= mask;

                // TODO: At least one of these two words would have to be left shifted before ORing - review and change accordingly
                //countValueStr.countValueU32Bit = (U32BIT)(msgRunTimeData.aDataWrds[eguParam.startWord] | msgRunTimeData.aDataWrds[eguParam.startWord + 1]);

                //below working (left shift did not work, right shift worked
                //countValueStr.countValueU32Bit = msgRunTimeData.aDataWrds[eguParam.startWord];
                //countValueStr.countValueU32Bit |= (U32BIT)(msgRunTimeData.aDataWrds[eguParam.startWord + 1] >> 15);

                //below also working !!! Choose one of the two depending on behaviour at customer's place
                countValueStr.countValueU32Bit = (U32BIT)(msgRunTimeData.aDataWrds[eguParam.startWord] >> 15);
                countValueStr.countValueU32Bit |= msgRunTimeData.aDataWrds[eguParam.startWord + 1];
            }
            else
            {
                //countValueStr.countValueU16Bit = (U16BIT) (msgRunTimeData.aDataWrds[eguParam.startWord] >> (int)eguParam.startBit);
                //U16BIT mask = (U16BIT) (0xFFFF >> (int)(16 - eguParam.length));
                //countValueStr.countValueU16Bit &= mask;

                countValueStr.countValueU16Bit = (U16BIT)(msgRunTimeData.aDataWrds[eguParam.startWord]);
            }

            if (eguParam.isReverseBits.ToUpper() == "YES")
            {
                //byte[] valAsBytes = BitConverter.GetBytes(countValue);
                //Array.Reverse(valAsBytes);
                //countValue = BitConverter.ToUInt16(valAsBytes, 0);

                if (eguParam.length > 16)
                {
                    countValueStr.countValueU32Bit = ReverseBitsU32BIT(countValueStr.countValueU32Bit);
                }
                else
                {
                    countValueStr.countValueU16Bit = ReverseBitsUShort(countValueStr.countValueU16Bit);
                }
            }

            bool isSignBit = false;

            if (eguParam.length > 16)
            {
                if (eguParam.dataType.ToUpper() == "INTEGER")
                {
                    if (((U32BIT)(countValueStr.countValueU32Bit & 0x80000000)) == 0x80000000) // Is 32nd bit (sign bit) 1?
                        isSignBit = true;
                }

                // If start bit within the word is not bit-0, then the value will have unwanted bits below/behind the start bit.
                // Right-shifting so that the actual start bit comes to bit-0 position will cause the unwanted bits to be thrown
                // off the value
                countValueStr.countValueU32Bit = (U32BIT)(countValueStr.countValueU32Bit >> (int)eguParam.startBit);
                U32BIT mask = (U32BIT) (0xFFFFFFFF >> (int)(32 - eguParam.length));
                countValueStr.countValueU32Bit &= mask;
            }
            else
            {
                //U16BIT signBit = 0;

                //if (eguParam.dataType.ToUpper() == "INTEGER" && eguParam.startBit != 0)
                //{
                //    signBit = (U16BIT) (countValueStr.countValueU16Bit & 0x8000);

                //    //countValueStr.countValueU16Bit &= 0x7FFF;   // Make 16th bit zero
                //}

                if (eguParam.dataType.ToUpper() == "INTEGER")
                {
                    if (((U16BIT)(countValueStr.countValueU16Bit & 0x8000)) == 0x8000) // Is 16th bit (sign bit) 1?
                        isSignBit = true;
                }

                // If start bit within the word is not bit-0, then the value will have unwanted bits below/behind the start bit.
                // Right-shifting so that the actual start bit comes to bit-0 position will cause the unwanted bits to be thrown
                // off the value
                countValueStr.countValueU16Bit = (U16BIT)(countValueStr.countValueU16Bit >> (int)eguParam.startBit);

                // If length is not 16, then bits above/ahead of the bit located at "length" will need to be removed.
                // This is done by preparing a mask that has only the "required" bits set to 1 and rest to 0. When this
                // mask is bit-wise ANDed with the value, the bits beyond "length" will be forced to zero
                U16BIT mask = (U16BIT)(0xFFFF >> (int)(16 - eguParam.length));
                countValueStr.countValueU16Bit &= mask;

                //if (eguParam.dataType.ToUpper() == "INTEGER" && eguParam.startBit != 0)
                //{
                //    countValueStr.countValueU16Bit |= signBit;
                //}
            }

            //if ((eguParam.dataType == "UNSIGNED_INTEGER") || (eguParam.dataType == "BCD"))
            if (eguParam.dataType.ToUpper() == "UNSIGNED")
            {
                //eguParam.value.u16Value = (U16BIT) (countValue * eguParam.scaleFactor + eguParam.offset);
                //eguParam.value.fValue = (float) (((U16BIT)countValue) * eguParam.scaleFactor + eguParam.offset);

                if (eguParam.length > 16)
                {
                    eguParam.value.fValue = (float)(((U32BIT)countValueStr.countValueU32Bit) * eguParam.scaleFactor + eguParam.offset);
                }
                else
                {
                    eguParam.value.fValue = (float)(((U16BIT)countValueStr.countValueU16Bit) * eguParam.scaleFactor + eguParam.offset);
                }
            }
            else if (eguParam.dataType.ToUpper() == "INTEGER")
            {
                //eguParam.value.s16Value = (S16BIT) (((S16BIT)countValue) * eguParam.scaleFactor + eguParam.offset);
                //eguParam.value.fValue = (float) (((S16BIT)countValue) * eguParam.scaleFactor + eguParam.offset);

                if (eguParam.length > 16)
                {
                    eguParam.value.fValue = (float)(((S32BIT)countValueStr.countValueU32Bit) * eguParam.scaleFactor + eguParam.offset);
                }
                else
                {
                    eguParam.value.fValue = (float)(((S16BIT)countValueStr.countValueU16Bit) * eguParam.scaleFactor + eguParam.offset);
                }

                if (isSignBit)
                {
                    eguParam.value.fValue = -Math.Abs(eguParam.value.fValue);
                }
            }
            //else if ((eguParam.dataType == "UNSIGNED_REAL") || (eguParam.dataType == "SIGNED_REAL"))
            else if (eguParam.dataType.ToUpper() == "REALIEEE754")
            {
                U32BIT extCountValue;

                if ((eguParam.dataType == "SIGNED_REAL") &&
                    (((countValueStr.countValueU16Bit >> (int)(eguParam.length - 1)) & 1) != 0)
                    )  /* Is sign bit 1? */
                {
                    //Make sure to extend the sign information
                    extCountValue = (U32BIT) (countValueStr.countValueU16Bit | (0xFFFFFFFF << (int)eguParam.length));
                }
                else
                {
                    extCountValue = countValueStr.countValueU16Bit;
                }

                eguParam.value.fValue = (float) (extCountValue * eguParam.scaleFactor + eguParam.offset);
            }
            else if (eguParam.dataType.ToUpper() == "CODED")
            {
                string tempStr;

                /* For coded types, we will not only populate the string value but also the raw value in u16Value field. This is to enable
                    utilities like "plot" to plot coded parameters */
                eguParam.value.u16Value = countValueStr.countValueU16Bit;

                // Use the computed value as an index into the coded string list
                List<string> codedValues = GetCodedValues(eguParam.codedType, codedTypes);

                if (codedValues.Count > eguParam.value.u16Value)
                {
                    tempStr = codedValues[eguParam.value.u16Value];
                }
                else
                {
                    tempStr = "!VAL_OOR";
                }

                eguParam.value.strValue = tempStr;
            }
            else
            {
                //qDebug() << __FUNCTION__ << "Unknown data type encountered";
            }

            return true;
        }

        List<string> GetCodedValues(string codedType, List<CodedType> listCodedTypes)
        {
            List<string> codedValues = new List<string>();

            foreach (CodedType ct in listCodedTypes)
            {
                if (ct.type == codedType)
                {
                    codedValues = ct.values;
                    break;
                }
            }

            return codedValues;
        }


        public bool DoEguConversionForAllParams(List<CodedType> codedTypes)
        {
            //foreach (EguParameter eguParam in eguParams)
            for (int i = 0; i < eguParams.Count; i++)
            {
                EguParameter eguParam = new EguParameter();
                eguParam = eguParams[i];
                if (DoEguConversionForParam(ref eguParam, codedTypes) == false)  // Doubt
                {
                    return false;
                }

                eguParams.RemoveAt(i);
                eguParams.Insert(i, eguParam);
            }

            return true;
        }

        public bool DoEguConversionForParam(string paraName, List<CodedType> codedTypes)
        {
            EguParameter eguParam = GetParameter(paraName);
            bool retVal = false;
            if (eguParam != null)
            {
                retVal = DoEguConversionForParam(ref eguParam, codedTypes);
            }
            else
            {
                retVal = false;
                //qDebug() << __FUNCTION__ << "GetParameter returned nullptr for parameter " << paraName;
            }
            return retVal;
        }

        public ulong getCombinedTT()
        {
            return combinedTT;
        }

        public string getFormattedTT()
        {
            ushort seconds, minutes, hours, milliseconds, microseconds;
            ulong days;

            const ulong µsPerDay = 86400L * 1000L * 1000L;   // 86,400,000,000
            const ulong µsPerHour = 3600L * 1000L * 1000L;   // 3,600,000,000
            const ulong µsPerMinute = 60L * 1000L * 1000L;   // 60,000,000
            const ulong µsPerSecond = 1L * 1000L * 1000L;    // 1,000,000
            const ulong µsPerMillisecond = 1L * 1000L;       // 1,000

            days = combinedTT / µsPerDay;
            ulong rem = combinedTT % µsPerDay;

            hours = (ushort)(rem / µsPerHour);
            rem = rem % µsPerHour;

            minutes = (ushort)(rem / µsPerMinute);
            rem = rem % µsPerMinute;

            seconds = (ushort)(rem / µsPerSecond);
            rem = rem % µsPerSecond;

            milliseconds = (ushort)(rem / µsPerMillisecond);
            rem = rem % µsPerMillisecond;

            microseconds = (ushort)rem;

            return string.Format("{0}:{1:D2}:{2:D2}:{3:D2}.{4:D3}", days, hours, 
                minutes, seconds, milliseconds);
        }

        /* Prepares a U16BIT buffer by populating it with the raw values of parameters after doing
         * reverse Egu conversion. This buffer may then by directly written to the 1553 Data Block
         * of this message */
        public void PopulateDataBlkUpdateBuffer(ref U16BIT[] buffer, List<CodedType> m_CodedTypes)
        {
            /* Zero out buffer */
            for (int i = 0; i < buffer.Length; i++)
            {
                buffer[i] = 0;
            }

            foreach (EguParameter eguParam in eguParams)
            {
                U16BIT[] rawValue = new U16BIT[2];

                /* Perform a reverse engg unit conversion */
                eguParam.GetRawValue(ref rawValue, m_CodedTypes);

                U16BIT mask = (U16BIT) (0xFFFF >> (16 - (int)eguParam.length));
                mask = (U16BIT) (mask << (int)eguParam.startBit);
                mask = (U16BIT) ~mask;
                buffer[eguParam.startWord] &= mask;
                buffer[eguParam.startWord] |= rawValue[0];

                if (eguParam.isReverseBits.ToUpper() == "YES")
                {
                    buffer[eguParam.startWord] = ReverseBitsUShort(buffer[eguParam.startWord]);
                }
            }
        }

        /* For parameters that are being edited, this function commits the changes made by the
        * user by writing the value in "modifiedValue" to "value" member */
        public void CommitParameterModifications()
        {
            foreach (EguParameter eguParam in eguParams)
            {
                if (eguParam.bEditInProgress == true)
                {
                    /* If the parameter was edited in the UI, transfer the edited value from "modifiedValue" variable
                     * to "value" variable, now that this edit is being committed */
                    eguParam.value = eguParam.modifiedValue;

                    eguParam.bEditInProgress = false;
                }
            }
        }

        public void DiscardParameterModifications()
        {
            foreach (EguParameter eguParam in eguParams)
            {
                eguParam.bEditInProgress = false;
            }
        }

        public void LoadDefaultData()
        {
            foreach (EguParameter eguParam in eguParams)
            {
                eguParam.LoadDefaultData();
            }
        }

        public void setTimeTagResolution(U16BIT newTimeTagResolution)
        {
            timeTagResolution = 0;
            switch (newTimeTagResolution)
            {
                case ddc1553Constants.TTResValues.ACE_TT_1US:
                    timeTagResolution = 1;
                    break;
                case ddc1553Constants.TTResValues.ACE_TT_2US:
                    timeTagResolution = 2;
                    break;
                case ddc1553Constants.TTResValues.ACE_TT_4US:
                    timeTagResolution = 4;
                    break;
                case ddc1553Constants.TTResValues.ACE_TT_8US:
                    timeTagResolution = 8;
                    break;
                case ddc1553Constants.TTResValues.ACE_TT_16US:
                    timeTagResolution = 16;
                    break;
                case ddc1553Constants.TTResValues.ACE_TT_32US:
                    timeTagResolution = 32;
                    break;
                case ddc1553Constants.TTResValues.ACE_TT_64US:
                    timeTagResolution = 64;
                    break;
            }
        }

        public void ResetRunTimeData()
        {
            //memset(&msgRunTimeData, 0, sizeof(MSGSTRUCT));
            msgRunTimeData.wType = 0;
            msgRunTimeData.wBlkSts = 0;
            msgRunTimeData.wTimeTag = 0;
            msgRunTimeData.wCmdWrd1 = 0;
            msgRunTimeData.wCmdWrd2 = 0;
            msgRunTimeData.wCmdWrd1Flg = 0;
            msgRunTimeData.wCmdWrd2Flg = 0;
            msgRunTimeData.wStsWrd1 = 0;
            msgRunTimeData.wStsWrd2 = 0;
            msgRunTimeData.wStsWrd1Flg = 0;
            msgRunTimeData.wStsWrd2Flg = 0;
            msgRunTimeData.wWordCount = 0;
            msgRunTimeData.aDataWrds = new U16BIT[32];
            for (int i = 0; i < 32; i++)
            {
                msgRunTimeData.aDataWrds[i] = 0;
            }
            msgRunTimeData.wBCCtrlWrd = 0;
            msgRunTimeData.wBCGapTime = 0;
            msgRunTimeData.wBCLoopBack1 = 0;
            msgRunTimeData.wTimeTag2 = 0;
            msgRunTimeData.wBCLoopBack1Flg = 0;
            msgRunTimeData.wTimeTag3 = 0;
        }

    }
}
