Example #1
0
	/**
	 * Determines if message bits 0 - 47 pass the Fleetsync CRC checksum 
	 * contained in bits 48 - 63, using a lookup table of CRC checksum values
	 * derived from the CRC-15 value, and verifies the message has even parity
	 */
	public static CRC check( RadioLog.Common.SafeBitArray msg )
	{
		CRC crc = CRC.UNKNOWN;
		
		int calculated = 1; //Starting value

		//Check even parity
		if( msg.Cardinality() % 2 == 0 )
		{
			//Iterate bits that are set and XOR running checksum with lookup value
			for (int i = msg.nextSetBit( 0 ); i >= 0 && i < 48; i = msg.nextSetBit( i+1 ) ) 
			{
				calculated ^= sCHECKSUMS[ i ];
			}
			
			if( calculated == getChecksum( msg ) )
			{
				crc = CRC.PASSED;
			}
			else
			{
				crc = CRC.FAILED_CRC;
			}
		}
		else
		{
			crc = CRC.FAILED_PARITY;
		}
		
		return crc;
	}
Example #2
0
 public P25MessageAssembler(P25MessageFramer framer)
 {
     mFramer        = framer;
     mMessageLength = mDUID.getMessageLength();
     mMessage       = new RadioLog.Common.SafeBitArray(mMessageLength);
     reset();
 }
Example #3
0
            /**
             * Sends instrumentation tap event to all registered listeners
             */
            private void sendTapEvent(RadioLog.Common.SafeBitArray bitset, Shift shift, bool decision)
            {
                foreach (IListener <SymbolEvent> tap in mDecoder.GetListeners())
                {
                    SymbolEvent sEvent = new SymbolEvent(bitset.CloneFromIndexToIndex(0, mSymbolLength), mSymbolLength, decision, shift);

                    tap.Receive(sEvent);
                }
            }
Example #4
0
	/**
	 * Returns the integer value of the 15 bit crc checksum
	 */
    public static int getChecksum( RadioLog.Common.SafeBitArray msg )
    {
    	int retVal = 0;
    	
    	for( int x = 0; x < 15; x++ )
    	{
    		if( msg[ x + 48 ] )
    		{
    			retVal += 1<<( 14 - x );
    		}
    	}
    	
    	return retVal;
    }
Example #5
0
        private Constellation getConstellation(RadioLog.Common.SafeBitArray message, int index)
        {
            int constellation = 0;

            for (int x = 0; x < 4; x++)
            {
                if (message[index + x])
                {
                    constellation += (1 << (3 - x));
                }
            }

            return(Constellation.fromValue(constellation));
        }
Example #6
0
        public static RadioLog.Common.SafeBitArray interleave(RadioLog.Common.SafeBitArray message, int start, int end)
        {
            RadioLog.Common.SafeBitArray original = message.CloneFromIndexToIndex(start, end);

            /* Clear block bits in source message */
            message.ClearRange(start, end);

            /* Iterate only the set bits in the original message and apply
             * the deinterleave -- we don't have to evaluate the 0 bits */
            for (int i = original.nextSetBit(0);
                 i >= 0 && i < INTERLEAVE.Length;
                 i = original.nextSetBit(i + 1))
            {
                message.SetBit(start + INTERLEAVE[i]);
            }

            return(message);
        }
Example #7
0
    /**
     * Determines the errant bit positions and returns them in an array of 
     * integer bit positions.
     * 
     * Note: currently only detects single-bit errors
     * 
     * @param msg to be checked for errors
     * @return - array of integer positions of bits that need flipped
     */
    public static int[] findBitErrors( RadioLog.Common.SafeBitArray msg )
    {
    	int[] retVal = null;
    	
    	int checksum = getChecksum( msg );
    	
		//Remove the initial fill value (1)
		checksum ^= 1;
		
		//Iterate set message bits, removing their respective checksum value
    	//from the transmitted checksum, to arrive at the remainder
		for (int i = msg.nextSetBit( 0 ); i >= 0 && i < 48; i = msg.nextSetBit( i+1 ) ) 
		{
			checksum ^= sCHECKSUMS[ i ];
		}
		
		//If at this point the checksum is 0, then we have a parity bit error
		if( checksum == 0 )
		{
			retVal = new int[ 1 ];
			retVal[ 0 ] = 63;
		}
		//Otherwise, try to lookup the syndrome for a single bit error
		else
		{
			for( int x = 0; x < 63; x++ )
			{
				if( checksum == sCHECKSUMS[ x ] )
				{
					//return this bit position
					retVal = new int[ 1 ];
					retVal[ 0 ] = x;
				}
			}
		}

		return retVal;
    }
Example #8
0
        public static TSBKMessage getMessage(int system, RadioLog.Common.SafeBitArray buffer)
        {
            int opcode = buffer.getInt(TSBKMessage.OPCODE);
            int vendor = buffer.getInt(TSBKMessage.VENDOR_ID);

            switch (vendor)
            {
            case 0:     //STANDARD
            {
                return(new TSBKMessage(system, buffer));
            }

            case 144:     //MOTOROLA
            {
                return(new TSBKMessage(system, buffer));
            }

            default:
            {
                return(new TSBKMessage(system, buffer));
            }
            }
        }
Example #9
0
        private CRC detectAndCorrect(int start, int end)
        {
            RadioLog.Common.SafeBitArray original = mMessage.CloneFromIndexToIndex(start, end);

            CRC retVal = CRCFleetsync.check(original);

            //Attempt to correct single-bit errors
            if (retVal == CRC.FAILED_PARITY)
            {
                int[] errorBitPositions = CRCFleetsync.findBitErrors(original);

                if (errorBitPositions != null)
                {
                    foreach (int errorBitPosition in errorBitPositions)
                    {
                        mMessage.flip(start + errorBitPosition);
                    }

                    retVal = CRC.CORRECTED;
                }
            }

            return(retVal);
        }
Example #10
0
        public void decode(RadioLog.Common.SafeBitArray message, int start, int end)
        {
            /* load each of the nodes with deinterleaved constellations */
            for (int index = 0; index < 49; index++)
            {
                Constellation c = getConstellation(message, index * 4);

                mConstellationNodes[index].setConstellation(c);
            }

            /* test to see if constellations are correct - otherwise correct them */
            ConstellationNode firstNode = mConstellationNodes[0];

            if (!firstNode.startsWith(Dibit.D0) || !firstNode.isCorrect())
            {
                firstNode.correctTo(Dibit.D0);
            }

            /* clear constellations from original message */
            message.ClearRange(start, end - start);

            /* replace with decoded values from the nodes */
            for (int index = 0; index < 49; index++)
            {
                ConstellationNode node = mConstellationNodes[index];

                if (node.firstBit())
                {
                    message.SetBit(start + (index * 2));
                }
                if (node.secondBit())
                {
                    message.SetBit(start + (index * 2) + 1);
                }
            }
        }
Example #11
0
 public P25Message(RadioLog.Common.SafeBitArray message, Decoders.P25.Reference.DataUnitID duid)
     : base()
 {
     mMessage = message;
     mDUID    = duid;
 }
Example #12
0
 public MessageAssembler(MessageFramer framer, int messageLength)
 {
     mFramer  = framer;
     mMessage = new RadioLog.Common.SafeBitArray(messageLength);
 }
Example #13
0
 public FleetsyncMessage(RadioLog.Common.SafeBitArray message)
 {
     mMessage = message;
     checkParity();
 }
Example #14
0
 public PDUMessage(RadioLog.Common.SafeBitArray message, Decoders.P25.Reference.DataUnitID duid) : base(message, duid)
 {
 }
Example #15
0
 public P25Message(RadioLog.Common.SafeBitArray message, Decoders.P25.Reference.DataUnitID duid)
     : base()
 {
     mMessage = message;
     mDUID = duid;
 }
Example #16
0
 public void dispose()
 {
     mMessage = null;
 }
Example #17
0
            private void checkComplete()
            {
                if (mDUID.Equals(Decoders.P25.Reference.DataUnitID.NID))
                {
                    int value = mMessage.getInt(Decoders.P25.Message.P25Message.DUID);

                    Decoders.P25.Reference.DataUnitID duid = Decoders.P25.Reference.DataUnitID.fromValue(value);

                    if (duid != Decoders.P25.Reference.DataUnitID.UNKN)
                    {
                        setDUID(duid);
                    }
                    else
                    {
                        mComplete = true;
                    }
                }
                else if (mDUID.Equals(Decoders.P25.Reference.DataUnitID.HDU) ||
                         mDUID.Equals(Decoders.P25.Reference.DataUnitID.LDU1) ||
                         mDUID.Equals(Decoders.P25.Reference.DataUnitID.LDU2) ||
                         mDUID.Equals(Decoders.P25.Reference.DataUnitID.PDU2) ||
                         mDUID.Equals(Decoders.P25.Reference.DataUnitID.PDU3) ||
                         mDUID.Equals(Decoders.P25.Reference.DataUnitID.TDU) ||
                         mDUID.Equals(Decoders.P25.Reference.DataUnitID.TDULC) ||
                         mDUID.Equals(Decoders.P25.Reference.DataUnitID.UNKN))
                {
                    mComplete = true;
                    mFramer.dispatch(new Decoders.P25.Message.P25Message(mMessage.Clone(), mDUID));
                }
                else if (mDUID.Equals(Decoders.P25.Reference.DataUnitID.PDU1))
                {
                    int blocks    = mMessage.getInt(Decoders.P25.Message.PDUMessage.PDU_HEADER_BLOCKS_TO_FOLLOW);
                    int padBlocks = mMessage.getInt(Decoders.P25.Message.PDUMessage.PDU_HEADER_PAD_BLOCKS);

                    int blockCount = blocks + padBlocks;

                    if (blockCount == 24 || blockCount == 32)
                    {
                        setDUID(Decoders.P25.Reference.DataUnitID.PDU2);
                    }
                    else if (blockCount == 36 || blockCount == 48)
                    {
                        setDUID(Decoders.P25.Reference.DataUnitID.PDU3);
                    }
                    else
                    {
                        mFramer.dispatch(new Decoders.P25.Message.PDUMessage(mMessage.Clone(), mDUID));
                        mComplete = true;
                    }
                }
                else if (mDUID.Equals(Decoders.P25.Reference.DataUnitID.TSBK1))
                {
                    /* Remove interleaving */
                    Decoders.P25.P25Interleave.deinterleave(mMessage, TSBK_BEGIN, TSBK_END);

                    /* Remove trellis encoding */
                    mFramer.mHalfRate.decode(mMessage, TSBK_BEGIN, TSBK_END);

                    /* Construct the message */
                    int tsbkSystem1 = mMessage.getInt(Decoders.P25.Message.P25Message.NAC);

                    RadioLog.Common.SafeBitArray tsbkBuffer1 = new RadioLog.Common.SafeBitArray(mMessage.CloneFromIndexToIndex(TSBK_BEGIN, TSBK_DECODED_END), 96);

                    Decoders.P25.Message.TSBKMessage tsbkMessage1 = Decoders.P25.Message.TSBKMessageFactory.getMessage(tsbkSystem1, tsbkBuffer1);

                    if (tsbkMessage1.isLastBlock())
                    {
                        mComplete = true;
                    }
                    else
                    {
                        setDUID(Decoders.P25.Reference.DataUnitID.TSBK2);
                        mMessage.SetPointer(TSBK_BEGIN);
                    }

                    mFramer.dispatch(tsbkMessage1);
                }
                else if (mDUID.Equals(Decoders.P25.Reference.DataUnitID.TSBK2))
                {
                    /* Remove interleaving */
                    Decoders.P25.P25Interleave.deinterleave(mMessage, TSBK_BEGIN, TSBK_END);

                    /* Remove trellis encoding */
                    mFramer.mHalfRate.decode(mMessage, TSBK_BEGIN, TSBK_END);

                    /* Construct the message */
                    int tsbkSystem2 = mMessage.getInt(Decoders.P25.Message.P25Message.NAC);

                    RadioLog.Common.SafeBitArray tsbkBuffer2 = new RadioLog.Common.SafeBitArray(mMessage.CloneFromIndexToIndex(TSBK_BEGIN, TSBK_DECODED_END), 98);

                    Decoders.P25.Message.TSBKMessage tsbkMessage2 = Decoders.P25.Message.TSBKMessageFactory.getMessage(tsbkSystem2, tsbkBuffer2);

                    if (tsbkMessage2.isLastBlock())
                    {
                        mComplete = true;
                    }
                    else
                    {
                        setDUID(Decoders.P25.Reference.DataUnitID.TSBK3);
                        mMessage.SetPointer(TSBK_BEGIN);
                    }

                    mFramer.dispatch(tsbkMessage2);
                }
                else if (mDUID.Equals(Decoders.P25.Reference.DataUnitID.TSBK3))
                {
                    /* Remove interleaving */
                    Decoders.P25.P25Interleave.deinterleave(mMessage, TSBK_BEGIN, TSBK_END);

                    /* Remove trellis encoding */
                    mFramer.mHalfRate.decode(mMessage, TSBK_BEGIN, TSBK_END);

                    /* Construct the message */
                    int tsbkSystem3 = mMessage.getInt(Decoders.P25.Message.P25Message.NAC);

                    RadioLog.Common.SafeBitArray tsbkBuffer3 = new RadioLog.Common.SafeBitArray(mMessage.CloneFromIndexToIndex(TSBK_BEGIN, TSBK_DECODED_END), 96);

                    Decoders.P25.Message.TSBKMessage tsbkMessage3 = Decoders.P25.Message.TSBKMessageFactory.getMessage(tsbkSystem3, tsbkBuffer3);

                    mComplete = true;

                    mFramer.dispatch(tsbkMessage3);
                }
                else
                {
                    mComplete = true;
                }
            }
Example #18
0
 public FleetsyncMessage(RadioLog.Common.SafeBitArray message)
 {
     mMessage = message;
     checkParity();
 }
Example #19
0
 public TSBKMessage(int system, RadioLog.Common.SafeBitArray message)
     : base(message, Reference.DataUnitID.TSBK1)
 {
     //
 }