public string[] Decode(byte[] DataBlockBuffer, string Time, out int NumOfMessagesDecoded) { // Define output data buffer string[] DataOut = new string[1000]; // Determine the size of the datablock int LengthOfDataBlockInBytes = DataBlockBuffer.Length; // Index into the array of record strings int DataOutIndex = 0; // Reset buffer indexes CurrentDataBufferOctalIndex = 0; int DataBufferIndexForThisExtraction = 0; // SIC/SAC Indexes int SIC_Index = 0; int SAC_Index = 0; // Save off SIC/SAC and time in the case they are not present // in each message. Some implementation have it only in the first record int SIC = 0; int SAC = 0; // Lenght of the current record's FSPECs int FSPEC_Length = 0; // The four possible FSPEC octets BitVector32 FourFSPECOctets = new BitVector32(); while ((DataBufferIndexForThisExtraction) < LengthOfDataBlockInBytes) { // Assume that there will be no more than 300 bytes in one record byte[] LocalSingleRecordBuffer = new byte[3000]; Array.Copy(DataBlockBuffer, DataBufferIndexForThisExtraction, LocalSingleRecordBuffer, 0, (LengthOfDataBlockInBytes - DataBufferIndexForThisExtraction)); // Get all four data words, but use only the number specifed // by the length of FSPEC words FourFSPECOctets = ASTERIX.GetFourFSPECOctets(LocalSingleRecordBuffer); // Determine Length of FSPEC fields in bytes FSPEC_Length = ASTERIX.DetermineLenghtOfFSPEC(LocalSingleRecordBuffer); // Check wether 010 is present if (FourFSPECOctets[Bit_Ops.Bit7] == true) { // Determine SIC/SAC Index SIC_Index = FSPEC_Length; SAC_Index = SIC_Index + 1; // Extract SIC/SAC Indexes. DataOut[DataOutIndex] = LocalSingleRecordBuffer[SIC_Index].ToString() + '/' + LocalSingleRecordBuffer[SAC_Index].ToString(); // Save off data for other records SIC = LocalSingleRecordBuffer[SIC_Index]; SAC = LocalSingleRecordBuffer[SAC_Index]; // Save of the current data buffer index so it can be used by // Decoder CurrentDataBufferOctalIndex = SAC_Index + 1; } else { CurrentDataBufferOctalIndex = FSPEC_Length; // Extract SIC/SAC Indexes. DataOut[DataOutIndex] = SIC.ToString() + '/' + SAC.ToString(); } /////////////////////////////////////////////////////////////////////////// // Populate the current SIC/SAC and Time stamp for this meesage // I048DataItems[ItemIDToIndex("010")].value = new ASTERIX.SIC_SAC_Time(SIC, SAC, ASTERIX.TimeOfReception); Reset_Currently_Present_Flags(); // Loop for each FSPEC and determine what data item is present for (int FSPEC_Index = 1; FSPEC_Index <= FSPEC_Length; FSPEC_Index++) { switch (FSPEC_Index) { case 1: // 010 Data Source Identifier if (FourFSPECOctets[Bit_Ops.Bit7] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 010:T"; I048DataItems[ItemIDToIndex("010")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("010")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 010:F"; } // 140 Time-of-Day if (FourFSPECOctets[Bit_Ops.Bit6] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 140:T"; I048DataItems[ItemIDToIndex("140")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("140")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 140:F"; } // 020 Target Report Descriptor if (FourFSPECOctets[Bit_Ops.Bit5] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 020:T"; I048DataItems[ItemIDToIndex("020")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("020")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 020:F"; } // 040 Measured Position in Slant Polar Coordinates if (FourFSPECOctets[Bit_Ops.Bit4] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 040:T"; I048DataItems[ItemIDToIndex("040")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("040")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 040:F"; } // 070 Mode-3/A Code in Octal Representation if (FourFSPECOctets[Bit_Ops.Bit3] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 070:T"; I048DataItems[ItemIDToIndex("070")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("070")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 070:F"; } // 090 Flight Level in Binary Representation if (FourFSPECOctets[Bit_Ops.Bit2] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 090:T"; I048DataItems[ItemIDToIndex("090")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("090")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 090:F"; } // 130 Radar Plot Characteristics if (FourFSPECOctets[Bit_Ops.Bit1] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 130:T"; I048DataItems[ItemIDToIndex("130")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("130")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 130:F"; } break; case 2: // 220 Aircraft Address if (FourFSPECOctets[Bit_Ops.Bit15] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 220:T"; I048DataItems[ItemIDToIndex("220")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("220")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 220:F"; } // 240 Aircraft Identification if (FourFSPECOctets[Bit_Ops.Bit14] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 240:T"; I048DataItems[ItemIDToIndex("240")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("240")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 240:F"; } // 250 Mode S MB Data if (FourFSPECOctets[Bit_Ops.Bit13] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 250:T"; I048DataItems[ItemIDToIndex("250")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("250")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 250:F"; } // 161 Track Number if (FourFSPECOctets[Bit_Ops.Bit12] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 161:T"; I048DataItems[ItemIDToIndex("161")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("161")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 161:F"; } // 042 Calculated Position in Cartesian Coordinates if (FourFSPECOctets[Bit_Ops.Bit11] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 042:T"; I048DataItems[ItemIDToIndex("042")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("042")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 042:F"; } // 200 Calculated Track Velocity in Polar Representation if (FourFSPECOctets[Bit_Ops.Bit10] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 200:T"; I048DataItems[ItemIDToIndex("200")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("200")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 200:F"; } // 170 Track Status if (FourFSPECOctets[Bit_Ops.Bit9] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 170:T"; I048DataItems[ItemIDToIndex("170")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("170")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 170:F"; } break; case 3: // 210 Track Quality if (FourFSPECOctets[Bit_Ops.Bit23] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 210:T"; I048DataItems[ItemIDToIndex("210")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("210")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 210:F"; } // 030 Warning/Error Conditions if (FourFSPECOctets[Bit_Ops.Bit22] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 030:T"; I048DataItems[ItemIDToIndex("030")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("030")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 030:F"; } // 080 Mode-3/A Code Confidence Indicator if (FourFSPECOctets[Bit_Ops.Bit21] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 080:T"; I048DataItems[ItemIDToIndex("080")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("080")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 080:F"; } // 100 Mode-C Code and Confidence Indicator if (FourFSPECOctets[Bit_Ops.Bit20] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 100:T"; I048DataItems[ItemIDToIndex("100")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("100")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 100:F"; } // 110 Height Measured by 3D Radar if (FourFSPECOctets[Bit_Ops.Bit19] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 110:T"; I048DataItems[ItemIDToIndex("110")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("110")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 110:F"; } // 120 Radial Doppler Speed if (FourFSPECOctets[Bit_Ops.Bit18] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 120:T"; I048DataItems[ItemIDToIndex("120")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("120")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 120:F"; } // 230 Communications / ACAS Capability and Flight Status if (FourFSPECOctets[Bit_Ops.Bit17] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 230:T"; I048DataItems[ItemIDToIndex("230")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("230")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 230:F"; } break; case 4: // 260 ACAS Resolution Advisory Report if (FourFSPECOctets[Bit_Ops.Bit31] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 260:T"; I048DataItems[ItemIDToIndex("260")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("260")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 260:F"; } // 55 Mode-1 Code in Octal Representation if (FourFSPECOctets[Bit_Ops.Bit30] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 55:T"; I048DataItems[ItemIDToIndex("055")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("055")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 55:F"; } // 50 Mode-2 Code in Octal Representation if (FourFSPECOctets[Bit_Ops.Bit29] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 50:T"; I048DataItems[ItemIDToIndex("050")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("050")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 50:F"; } // 65 Mode-1 Code Confidence Indicator if (FourFSPECOctets[Bit_Ops.Bit28] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 65:T"; I048DataItems[ItemIDToIndex("065")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("065")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 65:F"; } // 60 Mode-2 Code Confidence Indicator if (FourFSPECOctets[Bit_Ops.Bit27] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 60:T"; I048DataItems[ItemIDToIndex("060")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("060")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 60:F"; } if (FourFSPECOctets[Bit_Ops.Bit26] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " SPI:T"; I048DataItems[ItemIDToIndex("SPI")].HasBeenPresent = true; I048DataItems[ItemIDToIndex("SPI")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " SPI:F"; } if (FourFSPECOctets[Bit_Ops.Bit25] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " Reserved Expansion"; } break; // Handle errors default: DataOut[DataOutIndex] = DataOut[DataOutIndex] + " UKN:T"; break; } } DataOutIndex++; CAT48DecodeAndStore.Do(LocalSingleRecordBuffer); DataBufferIndexForThisExtraction = DataBufferIndexForThisExtraction + CurrentDataBufferOctalIndex + 1; } // Return decoded data NumOfMessagesDecoded = DataOutIndex; return(DataOut); }