/// <summary> /// Decodes an airborne position message. /// </summary> /// <param name="message"></param> private void DecodeAirbornePosition(AdsbMessage message) { message.MessageFormat = message.Type == 0 ? MessageFormat.NoPositionInformation : MessageFormat.AirbornePosition; var subMessage = message.AirbornePosition = new AirbornePositionMessage(); subMessage.SurveillanceStatus = (SurveillanceStatus)_BitStream.ReadByte(2); if (IsFineFormatTisb(message)) { message.TisbIcaoModeAFlag = _BitStream.ReadByte(1); } else { if (message.Type == 0) { _BitStream.Skip(1); } else { subMessage.NicB = (byte)(_BitStream.ReadBit() ? 2 : 0); } } var rawAltitude = _BitStream.ReadUInt16(12); var acCode = ((rawAltitude & 0xfe0) >> 1) | (rawAltitude & 0x0f); int?altitude = null; if ((rawAltitude & 0x10) != 0) { altitude = ModeSAltitudeConversion.CalculateBinaryAltitude(acCode); } else { altitude = ModeSAltitudeConversion.LookupGillhamAltitude(acCode); } if (message.Type < 20) { subMessage.BarometricAltitude = altitude; } else { subMessage.GeometricAltitude = altitude; } subMessage.PositionTimeIsExact = _BitStream.ReadBit(); subMessage.CompactPosition = ExtractCprCoordinate(message, 17); }
/// <summary> /// See interface docs. /// </summary> /// <param name="rawMessage"></param> /// <param name="start"></param> /// <param name="signalLevel"></param> /// <param name="isMlat"></param> /// <returns></returns> public ModeSMessage Translate(byte[] rawMessage, int start, int?signalLevel, bool isMlat) { if (Statistics == null) { throw new InvalidOperationException("Statistics must be provided before Translate can do any work"); } ModeSMessage result = null; var messageLength = rawMessage == null ? 0 : rawMessage.Length - start; if (messageLength > 6) { _BitStream.Initialise(rawMessage); _BitStream.Skip(start * 8); var downlinkFormatValue = _BitStream.ReadByte(5); if (downlinkFormatValue >= 24) { downlinkFormatValue = 24; _BitStream.Skip(-3); } bool isLongFrame = true; switch (downlinkFormatValue) { case 16: case 17: case 18: case 19: case 20: case 21: case 24: if (messageLength > 13) { result = new ModeSMessage(); } break; default: isLongFrame = false; result = new ModeSMessage(); break; } if (result != null) { result.SignalLevel = signalLevel; result.IsMlat = isMlat; result.DownlinkFormat = (DownlinkFormat)downlinkFormatValue; switch (result.DownlinkFormat) { case DownlinkFormat.ShortAirToAirSurveillance: DecodeShortAirToAirSurveillance(result); break; // DF0 case DownlinkFormat.SurveillanceAltitudeReply: DecodeSurveillanceAltitudeReply(result); break; // DF4 case DownlinkFormat.SurveillanceIdentityReply: DecodeSurveillanceIdentityReply(result); break; // DF5 case DownlinkFormat.AllCallReply: DecodeAllCallReply(result); break; // DF11 case DownlinkFormat.LongAirToAirSurveillance: DecodeLongAirToAirSurveillance(result); break; // DF16 case DownlinkFormat.ExtendedSquitter: DecodeExtendedSquitter(result); break; // DF17 case DownlinkFormat.ExtendedSquitterNonTransponder: DecodeExtendedSquitterNonTransponder(result); break; // DF18 case DownlinkFormat.MilitaryExtendedSquitter: DecodeMilitaryExtendedSquitter(result); break; // DF19 case DownlinkFormat.CommBAltitudeReply: DecodeCommBAltitudeReply(result); break; // DF20 case DownlinkFormat.CommBIdentityReply: DecodeCommBIdentityReply(result); break; // DF21 case DownlinkFormat.CommD: DecodeCommD(result); break; // DF24 } if (Statistics != null) { Statistics.Lock(r => { ++r.ModeSMessagesReceived; ++r.ModeSDFStatistics[(int)result.DownlinkFormat].MessagesReceived; if (isLongFrame) { ++r.ModeSLongFrameMessagesReceived; } else { ++r.ModeSShortFrameMessagesReceived; } }); } } } return(result); }
public void BitStream_Skip_Jumps_Over_Bits_In_The_Stream() { var binary = "11001010001101011101001111110000"; for (int i = 0; i < binary.Length; ++i) { var expectedBit = binary[i] == '1'; _BitStream.Initialise(ParseBinary(binary)); _BitStream.Skip(i); Assert.AreEqual(expectedBit, _BitStream.ReadBit(), "Expected {0} after skipping {1} bits, ReadBit returned {2}", expectedBit, i, !expectedBit); } }
/// <summary> /// See interface docs. /// </summary> /// <param name="rawMessage"></param> /// <param name="start"></param> /// <returns></returns> public ModeSMessage Translate(byte[] rawMessage, int start) { ModeSMessage result = null; var messageLength = rawMessage == null ? 0 : rawMessage.Length - start; if (messageLength > 6) { _BitStream.Initialise(rawMessage); _BitStream.Skip(start * 8); var downlinkFormatValue = _BitStream.ReadByte(5); if (downlinkFormatValue >= 24) { downlinkFormatValue = 24; _BitStream.Skip(-3); } bool isLongFrame = true; switch (downlinkFormatValue) { case 16: case 17: case 18: case 19: case 20: case 21: case 24: if (messageLength > 13) { result = new ModeSMessage(); } break; default: isLongFrame = false; result = new ModeSMessage(); break; } if (result != null) { result.DownlinkFormat = (DownlinkFormat)downlinkFormatValue; switch (result.DownlinkFormat) { case DownlinkFormat.ShortAirToAirSurveillance: DecodeShortAirToAirSurveillance(result); break; // DF0 case DownlinkFormat.SurveillanceAltitudeReply: DecodeSurveillanceAltitudeReply(result); break; // DF4 case DownlinkFormat.SurveillanceIdentityReply: DecodeSurveillanceIdentityReply(result); break; // DF5 case DownlinkFormat.AllCallReply: DecodeAllCallReply(result); break; // DF11 case DownlinkFormat.LongAirToAirSurveillance: DecodeLongAirToAirSurveillance(result); break; // DF16 case DownlinkFormat.ExtendedSquitter: DecodeExtendedSquitter(result); break; // DF17 case DownlinkFormat.ExtendedSquitterNonTransponder: DecodeExtendedSquitterNonTransponder(result); break; // DF18 case DownlinkFormat.MilitaryExtendedSquitter: DecodeMilitaryExtendedSquitter(result); break; // DF19 case DownlinkFormat.CommBAltitudeReply: DecodeCommBAltitudeReply(result); break; // DF20 case DownlinkFormat.CommBIdentityReply: DecodeCommBIdentityReply(result); break; // DF21 case DownlinkFormat.CommD: DecodeCommD(result); break; // DF24 } if (_Statistics.Lock != null) { lock (_Statistics.Lock) { ++_Statistics.ModeSMessagesReceived; ++_Statistics.ModeSDFCount[(int)result.DownlinkFormat]; if (isLongFrame) { ++_Statistics.ModeSLongFrameMessagesReceived; } else { ++_Statistics.ModeSShortFrameMessagesReceived; } } } } } return(result); }