/// <summary> /// Decodes a coarse format TIS-B airborne position message. /// </summary> /// <param name="message"></param> private void DecodeCoarseTisbAirbornePosition(AdsbMessage message) { message.MessageFormat = MessageFormat.CoarseTisbAirbornePosition; var subMessage = message.CoarseTisbAirbornePosition = new CoarseTisbAirbornePosition(); message.TisbIcaoModeAFlag = _BitStream.ReadByte(1); subMessage.SurveillanceStatus = (SurveillanceStatus)_BitStream.ReadByte(2); subMessage.ServiceVolumeID = _BitStream.ReadByte(4); var rawAltitude = _BitStream.ReadUInt16(12); var acCode = ((rawAltitude & 0xfe0) >> 1) | (rawAltitude & 0x0f); if ((rawAltitude & 0x10) != 0) { subMessage.BarometricAltitude = ModeSAltitudeConversion.CalculateBinaryAltitude(acCode); } else { subMessage.BarometricAltitude = ModeSAltitudeConversion.LookupGillhamAltitude(acCode); } var groundTrackValid = _BitStream.ReadBit(); var groundTrack = _BitStream.ReadByte(5); var groundSpeed = _BitStream.ReadByte(6); if (groundTrackValid) { subMessage.GroundTrack = (double)groundTrack * 11.25; } subMessage.GroundSpeed = (double)groundSpeed * 16.0; subMessage.CompactPosition = ExtractCprCoordinate(message, 12, ignoreMessageType: true); }
/// <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); }
private void ExtractAltitudeCode(ModeSMessage reply) { reply.Altitude = _BitStream.ReadUInt16(13); reply.AltitudeIsMetric = (reply.Altitude & 0x40) != 0; if (!reply.AltitudeIsMetric.Value) { int?decodedAltitude = ((reply.Altitude & 0x1F80) >> 2) | ((reply.Altitude & 0x20) >> 1) | (reply.Altitude & 0x0f); if ((reply.Altitude & 0x10) != 0) { decodedAltitude = ModeSAltitudeConversion.CalculateBinaryAltitude(decodedAltitude.Value); } else { decodedAltitude = ModeSAltitudeConversion.LookupGillhamAltitude(decodedAltitude.Value); } reply.Altitude = decodedAltitude; } }
/// <summary> /// Decodes an aircraft status message. /// </summary> /// <param name="message"></param> private void DecodeAircraftStatus(AdsbMessage message) { message.MessageFormat = MessageFormat.AircraftStatus; var subMessage = message.AircraftStatus = new AircraftStatusMessage(); subMessage.AircraftStatusType = (AircraftStatusType)_BitStream.ReadByte(3); switch (subMessage.AircraftStatusType) { case AircraftStatusType.EmergencyStatus: var emergency = subMessage.EmergencyStatus = new EmergencyStatus(); emergency.EmergencyState = (EmergencyState)_BitStream.ReadByte(3); var modeA = (short)_BitStream.ReadUInt16(13); if (modeA != 0) { emergency.Squawk = ModeS.ModeATranslator.DecodeModeA(modeA); } break; case AircraftStatusType.TcasResolutionAdvisoryBroadcast: var tcas = subMessage.TcasResolutionAdvisory = new TcasResolutionAdvisory(); var araCoding = _BitStream.ReadBit(); var araValue = (short)_BitStream.ReadUInt16(13); tcas.ResolutionAdvisoryComplement = (ResolutionAdvisoryComplement)_BitStream.ReadByte(4); tcas.ResolutionAdvisoryTerminated = _BitStream.ReadBit(); tcas.MultipleThreatEncounter = _BitStream.ReadBit(); if (araCoding) { tcas.SingleThreatResolutionAdvisory = (SingleThreatResolutionAdvisory)araValue; } else if (tcas.MultipleThreatEncounter) { tcas.MultipleThreatResolutionAdvisory = (MultipleThreatResolutionAdvisory)araValue; } switch (_BitStream.ReadByte(2)) { case 1: tcas.ThreatIcao24 = (int)_BitStream.ReadUInt32(24); break; case 2: var threatAltitude = _BitStream.ReadUInt16(13); var threatRange = _BitStream.ReadByte(7); var threatBearing = _BitStream.ReadByte(6); var strippedAltitude = ((threatAltitude & 0x1F80) >> 2) | ((threatAltitude & 0x20) >> 1) | (threatAltitude & 0x0f); tcas.ThreatAltitude = ModeSAltitudeConversion.LookupGillhamAltitude(strippedAltitude); if (threatRange > 0) { tcas.ThreatRange = ((float)(threatRange - 1) / 10F) + 0.05F; tcas.ThreatRangeExceeded = threatRange == 127; } if (threatBearing > 0 && threatBearing < 61) { tcas.ThreatBearing = (short)((threatBearing - 1) * 6); } break; } break; } }