void SiiOsDebugChannelDisable(SiiOsalDebugChannels_e channel)
{
#if defined(DEBUG)
	uint8_t index =ChannelIndex(channel);
	uint8_t mask  =ChannelMask(channel) ;
    DebugChannelMasks[index] &= ~mask;
#endif
}
bool_t SiiOsDebugChannelIsEnabled(SiiOsalDebugChannels_e channel)
{
#if defined(DEBUG)
	uint8_t index = ChannelIndex(channel);
	uint8_t mask  = ChannelMask(channel) ;
    return (DebugChannelMasks[index] & mask)?true:false;
#else
    return false;
#endif
}
    bool AsyncDigitalAnalogPacket::integrityCheck(const WirelessPacket& packet)
    {
        WirelessPacket::Payload payload = packet.payload();

        //verify the payload size
        if(payload.size() < PAYLOAD_OFFSET_CHANNEL_DATA)
        {
            //payload is too small to be valid
            return false;
        }

        //verify the delivery stop flags are what we expected
        if(!packet.deliveryStopFlags().pc)
        {
            //packet not intended for the PC
            return false;
        }

        //read the data type
        uint8 dataType = payload.read_uint8(PAYLOAD_OFFSET_DATA_TYPE);

        //verify the data type
        if(dataType < WirelessTypes::dataType_first || dataType > WirelessTypes::dataType_last)
        {
            //the data type is invalid
            return false;
        }

        //verify the packet type is correct
        if(packet.type() != packetType_AsyncDigitalAnalog)
        {
            //packet is not an Async Digital packet
            return false;
        }

        //calculate the number of active channels
        uint32 channels = ChannelMask(payload.read_uint16(PAYLOAD_OFFSET_CHANNEL_MASK)).count();

        //check that there are active channels
        if(channels == 0)
        {
            //no active channels
            return false;
        }

        //packet looks valid
        return true;
    }
    void DatalogDownloader::parseTriggerHeader_v1()
    {
        //TODO: What if an exception is thrown in here??

        //reset the sweep count
        m_sweepCount = 0;

        //move passed the start of header bytes
        m_nodeMemory->skipBytes(3);

        //read the trigger type
        m_sessionInfo.triggerType = static_cast<WirelessTypes::TriggerType>(m_nodeMemory->read_uint8());

        //read the header version
        uint8 versionMajor = m_nodeMemory->read_uint8();
        uint8 versionMinor = m_nodeMemory->read_uint8();
        Version headerVersion(versionMajor, versionMinor);

        //read the number of bytes before the channel data
        uint16 bytesBeforeData = m_nodeMemory->read_uint16();
        uint32 byteCounter = m_nodeMemory->readIndex();    //used to calculate if we need to later consume (throw out) bytes that we don't know how to parse

        //read the number of sweeps
        m_sessionInfo.numSweeps = m_nodeMemory->read_uint16();

        //Header Version 2.1+
        if(headerVersion >= HEADER_VERSION_2_1)
        {
            //the number of sweeps in the header should be multiplied by 100
            m_sessionInfo.numSweeps *= 100;
        }

        //read the session index
        m_sessionInfo.sessionIndex = m_nodeMemory->read_uint16();

        //read the active channel mask
        m_sessionInfo.activeChannels = ChannelMask(m_nodeMemory->read_uint16());

        //read the sample rate
        uint16 sampleRateVal = m_nodeMemory->read_uint16();

        //if it is an armed datalogging rate, we need to convert it to a WirelessSampleRate
        //Note: if not a datalogging rate, this will just cast it to a WirelessSampleRate without conversion.
        WirelessTypes::WirelessSampleRate rate = WirelessTypes::dataloggingRateToSampleRate(sampleRateVal);
        m_sessionInfo.sampleRate = SampleRate::FromWirelessEepromValue(rate);
        m_sessionInfo.timeBetweenSweeps = m_sessionInfo.sampleRate.samplePeriod().getNanoseconds();

        if(headerVersion >= HEADER_VERSION_2_0)
        {
            //read the data type
            m_sessionInfo.dataType = static_cast<WirelessTypes::DataType>(m_nodeMemory->read_uint8());

            m_nodeMemory->skipBytes(1);    //unused byte
        }
        else
        {
            //no data type in the header, always uint16
            m_sessionInfo.dataType = WirelessTypes::dataType_uint16_12bitRes;
        }

        m_sessionInfo.valueType = WirelessTypes::dataTypeToValueType(m_sessionInfo.dataType);

        //read the number of user entered bytes
        uint16 numUserBytes = m_nodeMemory->read_uint16();

        //read the user entered string
        m_sessionInfo.userString = m_nodeMemory->read_string(numUserBytes);

        //if the user string is an odd number of bytes
        if(m_sessionInfo.userString.length() % 2 != 0)
        {
            //the data has 1 extra byte (always even), need to throw it out
            m_nodeMemory->skipBytes(1);

            if(headerVersion <= HEADER_VERSION_2_1)
            {
                //there is a bug in header version 2.1 and below where the
                //extra user byte isn't added to the bytesBeforeData count
                bytesBeforeData += 1;
            }
        }

        //====================================================
        //MOVE PASSED ANY EXTRA BYTES
        m_nodeMemory->skipBytes(bytesBeforeData - (m_nodeMemory->readIndex() - byteCounter));
        //====================================================

        //read the number of bytes per channel
        uint16 bytesPerChannel = m_nodeMemory->read_uint16();

        //loop through all of the active channels to get channel action information
        uint8 channelItr = 0;
        uint8 lastChannel = m_sessionInfo.activeChannels.lastChEnabled();

        WirelessChannel::ChannelId chId;
        WirelessTypes::CalCoef_EquationType equation;
        WirelessTypes::CalCoef_Unit unit;
        float slope;
        float offset;

        for(channelItr = 1; channelItr <= lastChannel; ++channelItr)
        {
            //only contains channel action info if the channel is in the data
            if(m_sessionInfo.activeChannels.enabled(channelItr))
            {
                byteCounter = m_nodeMemory->readIndex();

                chId = static_cast<WirelessChannel::ChannelId>(channelItr);

                //read the channel action equation
                equation = static_cast<WirelessTypes::CalCoef_EquationType>(m_nodeMemory->read_uint8());

                //read the channel action unit
                unit = static_cast<WirelessTypes::CalCoef_Unit>(m_nodeMemory->read_uint8());

                //check for uninitialized value
                if(unit == 0xAA || unit == 0xFF)
                {
                    unit = WirelessTypes::unit_none;
                }

                //read the channel action slope
                slope = m_nodeMemory->read_float(Utils::littleEndian);

                //read the channel action offset
                offset = m_nodeMemory->read_float(Utils::littleEndian);

                //add the cal coefficients to the session info
                m_sessionInfo.calCoefficients[chId] = CalCoefficients(equation, unit, LinearEquation(slope, offset));

                //====================================================
                //MOVE PASSED ANY EXTRA BYTES
                m_nodeMemory->skipBytes(bytesPerChannel - (m_nodeMemory->readIndex() - byteCounter));
                //====================================================
            }
        }

        //read the number of bytes before the end of the header
        uint16 bytesBeforeEnd = m_nodeMemory->read_uint16();
        Utils::checkBounds_min(bytesBeforeEnd, static_cast<uint16>(8));  //seems to be a bug where this number is less than what is actually there (8 is normal)
        byteCounter = m_nodeMemory->readIndex();

        //read the timestamp bytes
        uint32 timestampSeconds = m_nodeMemory->read_uint32();
        uint32 timestampNanos = m_nodeMemory->read_uint32();

        //build the full nanosecond resolution timestamp
        m_sessionInfo.timestamp = ((static_cast<uint64>(timestampSeconds) * TimeSpan::NANOSECONDS_PER_SECOND) + timestampNanos);

        //====================================================
        //MOVE PASSED ANY EXTRA BYTES
        m_nodeMemory->skipBytes(bytesBeforeEnd - (m_nodeMemory->readIndex() - byteCounter));
        //====================================================

        //set the startOfTrigger flag to true
        m_sessionInfo.startOfTrigger = true;
    }
    void DatalogDownloader::parseTriggerHeader_v2()
    {
        //TODO: What if an exception is thrown in here??

        uint8 headerId = m_nodeMemory->read_uint8();

        if(headerId == NodeMemory_v2::REFRESH_HEADER_ID)
        {
            //nothing changed, just getting more sweeps of data
            m_nodeMemory->skipBytes(1); //skip sweep count
        }
        else if(headerId == NodeMemory_v2::SESSION_CHANGE_HEADER_ID)
        {
            //reset the sweep count
            m_sweepCount = 0;

            m_nodeMemory->skipBytes(1); //skip sweep count

            //read the timestamp
            m_sessionInfo.timestamp = m_nodeMemory->read_uint64(Utils::littleEndian);

            //read the session index
            m_sessionInfo.sessionIndex = m_nodeMemory->read_uint16(Utils::littleEndian);
        }
        else if(headerId == NodeMemory_v2::BLOCK_HEADER_ID)
        {
            //reset the sweep count
            m_sweepCount = 0;

            m_nodeMemory->skipBytes(5); //skip version number, header size, sweep count, and block index

            m_sessionInfo.sessionIndex = m_nodeMemory->read_uint16(Utils::littleEndian);;

            //set the startOfTrigger flag to true
            m_sessionInfo.startOfTrigger = true;

            m_sessionInfo.timestamp = m_nodeMemory->read_uint64(Utils::littleEndian);

            //read the sample rate
            uint8 sampleRateVal = m_nodeMemory->read_uint8();

            //if it is an armed datalogging rate, we need to convert it to a WirelessSampleRate
            //Note: if not a datalogging rate, this will just cast it to a WirelessSampleRate without conversion.
            WirelessTypes::WirelessSampleRate rate = WirelessTypes::dataloggingRateToSampleRate(sampleRateVal);
            m_sessionInfo.sampleRate = SampleRate::FromWirelessEepromValue(rate);
            m_sessionInfo.timeBetweenSweeps = m_sessionInfo.sampleRate.samplePeriod().getNanoseconds();

            //read the active channel mask
            m_sessionInfo.activeChannels = ChannelMask(m_nodeMemory->read_uint16(Utils::littleEndian));

            //read the data type
            m_sessionInfo.dataType = static_cast<WirelessTypes::DataType>(m_nodeMemory->read_uint8());
            m_sessionInfo.valueType = WirelessTypes::dataTypeToValueType(m_sessionInfo.dataType);

            //loop through all of the active channels to get channel action information
            uint8 channelItr = 0;
            uint8 lastChannel = m_sessionInfo.activeChannels.lastChEnabled();

            WirelessChannel::ChannelId chId;
            WirelessTypes::CalCoef_EquationType equation;
            WirelessTypes::CalCoef_Unit unit;
            float slope;
            float offset;

            for(channelItr = 1; channelItr <= lastChannel; ++channelItr)
            {
                //only contains channel action info if the channel is in the data
                if(m_sessionInfo.activeChannels.enabled(channelItr))
                {
                    chId = static_cast<WirelessChannel::ChannelId>(channelItr);

                    //read the channel action equation
                    equation = static_cast<WirelessTypes::CalCoef_EquationType>(m_nodeMemory->read_uint8());

                    //read the channel action unit
                    unit = static_cast<WirelessTypes::CalCoef_Unit>(m_nodeMemory->read_uint8());

                    //check for uninitialized value
                    if(unit == 0xAA || unit == 0xFF)
                    {
                        unit = WirelessTypes::unit_none;
                    }

                    //read the channel action slope
                    slope = m_nodeMemory->read_float(Utils::littleEndian);

                    //read the channel action offset
                    offset = m_nodeMemory->read_float(Utils::littleEndian);

                    //add the cal coefficients to the session info
                    m_sessionInfo.calCoefficients[chId] = CalCoefficients(equation, unit, LinearEquation(slope, offset));
                }
            }
        }
        else
        {
            //shouldn't be parsing invalid headers at this point
            assert(false);
        }
    }
    bool BufferedLdcPacket::integrityCheck(const WirelessPacket& packet)
    {
        WirelessPacket::Payload payload = packet.payload();

        //verify the payload size
        if(payload.size() < PAYLOAD_OFFSET_CHANNEL_DATA)
        {
            //payload must be at least a certain length
            return false;
        }

        //verify the app id
        if(payload.read_uint8(PAYLOAD_OFFSET_APP_ID) != APP_ID_VAL)
        {
            //application id is incorrect
            return false;
        }

        //verify the delivery stop flags are what we expected
        if(!packet.deliveryStopFlags().pc)
        {
            //packet not intended for the PC
            return false;
        }

        //read the data type
        uint8 dataType = payload.read_uint8(PAYLOAD_OFFSET_DATA_TYPE);

        //verify the data type
        if(dataType < WirelessTypes::dataType_first || dataType > WirelessTypes::dataType_last)
        {
            //the data type is invalid
            return false;
        }

        //verify the packet type is correct
        if(packet.type() != packetType_BufferedLDC)
        {
            //packet is not a Buffered LDC packet
            return false;
        }

        //calculate the number of active channels
        uint32 channels = ChannelMask(payload.read_uint8(PAYLOAD_OFFSET_CHANNEL_MASK)).count();

        //calculate the size of a single data point
        uint32 dataSize = WirelessTypes::dataTypeSize(static_cast<WirelessTypes::DataType>(dataType));

        uint32 recordSize = channels * dataSize;

        //if record size is zero, something is wrong. Bail now before divide by zero
        if(recordSize <= 0)
        {
            return false;
        }

        //the number of channel data bytes
        size_t numChannelBytes = payload.size() - PAYLOAD_OFFSET_CHANNEL_DATA;

        //verify that there are actually channel data bytes
        if(numChannelBytes == 0)
        {
            return false;
        }

        //verify the payload contains a correct number of bytes
        if(numChannelBytes % recordSize != 0)
        {
            return false;
        }

        //packet looks valid
        return true;
    }