public string[] Decode(byte[] DataBlockBuffer, string Time, out int NumOfMessagesDecoded) { // Define output data buffer string[] DataOut = new string[2000]; // 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; // Lenght of the current record's FSPECs int FSPEC_Length = 0; // The first four possible FSPEC octets BitVector32 FourFSPECOctets = new BitVector32(); // The fifth FSPEC octet in the case RE or SP field is present BitVector32 TheFifthFSPECOctet = new BitVector32(); while (DataBufferIndexForThisExtraction < LengthOfDataBlockInBytes) { // Assume that there will be no more than 200 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); TheFifthFSPECOctet = ASTERIX.GetFifthFSPECOctet(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 of the current data buffer index so it can be used by // Decoder CurrentDataBufferOctalIndex = SAC_Index + 1; } else { // Extract SIC/SAC Indexes. DataOut[DataOutIndex] = "---" + '/' + "---"; } /////////////////////////////////////////////////////////////////////////// // Populate the current SIC/SAC and Time stamp for this meesage // I062DataItems[ItemIDToIndex("010")].value = new ASTERIX.SIC_SAC_Time(LocalSingleRecordBuffer[SIC_Index], LocalSingleRecordBuffer[SAC_Index], ASTERIX.TimeOfReception); // 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"; I062DataItems[ItemIDToIndex("010")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("010")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 010:F"; I062DataItems[ItemIDToIndex("010")].CurrentlyPresent = false; } // Spare bit if (FourFSPECOctets[Bit_Ops.Bit6] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " SPR:T"; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " SPR:F"; } // 015 Service Identification if (FourFSPECOctets[Bit_Ops.Bit5] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 015:T"; I062DataItems[ItemIDToIndex("015")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("015")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 015:F"; I062DataItems[ItemIDToIndex("015")].CurrentlyPresent = false; } // 070 Time Of Track Information if (FourFSPECOctets[Bit_Ops.Bit4] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 070:T"; I062DataItems[ItemIDToIndex("070")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("070")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 070:F"; I062DataItems[ItemIDToIndex("070")].CurrentlyPresent = false; } // 105 Calculated Track Position (WGS-84) if (FourFSPECOctets[Bit_Ops.Bit3] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 105:T"; I062DataItems[ItemIDToIndex("105")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("105")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 105:F"; I062DataItems[ItemIDToIndex("105")].CurrentlyPresent = false; } // 100 Calculated Track Position (Cartesian) if (FourFSPECOctets[Bit_Ops.Bit2] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 100:T"; I062DataItems[ItemIDToIndex("100")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("100")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 100:F"; I062DataItems[ItemIDToIndex("100")].CurrentlyPresent = false; } // 185 Calculated Track Velocity (Cartesian) if (FourFSPECOctets[Bit_Ops.Bit1] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 185:T"; I062DataItems[ItemIDToIndex("185")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("185")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 185:F"; I062DataItems[ItemIDToIndex("185")].CurrentlyPresent = false; } break; case 2: // 210 Calculated Acceleration (Cartesian) if (FourFSPECOctets[Bit_Ops.Bit15] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 210:T"; I062DataItems[ItemIDToIndex("210")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("210")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 210:F"; I062DataItems[ItemIDToIndex("210")].CurrentlyPresent = false; } // 060 Track Mode 3/A Code if (FourFSPECOctets[Bit_Ops.Bit14] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 060:T"; I062DataItems[ItemIDToIndex("060")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("060")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 060:F"; I062DataItems[ItemIDToIndex("060")].CurrentlyPresent = false; } // 245 Target Identification if (FourFSPECOctets[Bit_Ops.Bit13] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 245:T"; I062DataItems[ItemIDToIndex("245")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("245")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 245:F"; I062DataItems[ItemIDToIndex("245")].CurrentlyPresent = false; } // 380 Aircraft Derived Data if (FourFSPECOctets[Bit_Ops.Bit12] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 380:T"; I062DataItems[ItemIDToIndex("380")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("380")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 380:F"; I062DataItems[ItemIDToIndex("380")].CurrentlyPresent = false; } // 040 Track Number if (FourFSPECOctets[Bit_Ops.Bit11] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 040:T"; I062DataItems[ItemIDToIndex("040")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("040")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 040:F"; I062DataItems[ItemIDToIndex("040")].CurrentlyPresent = false; } // 080 Track Status if (FourFSPECOctets[Bit_Ops.Bit10] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 080:T"; I062DataItems[ItemIDToIndex("080")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("080")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 080:F"; I062DataItems[ItemIDToIndex("080")].CurrentlyPresent = false; } // 290 System Track Update Ages if (FourFSPECOctets[Bit_Ops.Bit9] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 290:T"; I062DataItems[ItemIDToIndex("290")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("290")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 290:F"; I062DataItems[ItemIDToIndex("290")].CurrentlyPresent = false; } break; case 3: // 200 Mode of Movement if (FourFSPECOctets[Bit_Ops.Bit23] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 200:T"; I062DataItems[ItemIDToIndex("200")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("200")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 200:F"; I062DataItems[ItemIDToIndex("200")].CurrentlyPresent = false; } // 295 Track Data Ages if (FourFSPECOctets[Bit_Ops.Bit22] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 295:T"; I062DataItems[ItemIDToIndex("295")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("295")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 295:F"; I062DataItems[ItemIDToIndex("295")].CurrentlyPresent = false; } // 136 Measured Flight Level if (FourFSPECOctets[Bit_Ops.Bit21] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 136:T"; I062DataItems[ItemIDToIndex("136")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("136")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 136:F"; I062DataItems[ItemIDToIndex("136")].CurrentlyPresent = false; } // 130 Calculated Track Geometric Altitude if (FourFSPECOctets[Bit_Ops.Bit20] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 130:T"; I062DataItems[ItemIDToIndex("130")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("130")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 130:F"; I062DataItems[ItemIDToIndex("130")].CurrentlyPresent = false; } // 135 Calculated Track Barometric Altitude if (FourFSPECOctets[Bit_Ops.Bit19] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 135:T"; I062DataItems[ItemIDToIndex("135")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("135")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 135:F"; I062DataItems[ItemIDToIndex("135")].CurrentlyPresent = false; } // 220 Calculated Rate Of Climb/Descent if (FourFSPECOctets[Bit_Ops.Bit18] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 220:T"; I062DataItems[ItemIDToIndex("220")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("220")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 220:F"; I062DataItems[ItemIDToIndex("220")].CurrentlyPresent = false; } // 390 Flight Plan Related Data if (FourFSPECOctets[Bit_Ops.Bit17] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 390:T"; I062DataItems[ItemIDToIndex("390")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("390")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 390:F"; I062DataItems[ItemIDToIndex("390")].CurrentlyPresent = false; } break; case 4: // 270 Target Size & Orientation if (FourFSPECOctets[Bit_Ops.Bit31] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 270:T"; I062DataItems[ItemIDToIndex("270")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("270")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 270:F"; I062DataItems[ItemIDToIndex("270")].CurrentlyPresent = false; } // 300 Vehicle Fleet Identification if (FourFSPECOctets[Bit_Ops.Bit30] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 300:T"; I062DataItems[ItemIDToIndex("300")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("300")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 300:F"; I062DataItems[ItemIDToIndex("300")].CurrentlyPresent = false; } // 110 Mode 5 Data reports & Extended Mode 1 Code if (FourFSPECOctets[Bit_Ops.Bit29] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 110:T"; I062DataItems[ItemIDToIndex("110")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("110")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 110:F"; I062DataItems[ItemIDToIndex("110")].CurrentlyPresent = false; } // 120 Track Mode 2 Code if (FourFSPECOctets[Bit_Ops.Bit28] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 120:T"; I062DataItems[ItemIDToIndex("120")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("120")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 120:F"; I062DataItems[ItemIDToIndex("120")].CurrentlyPresent = false; } // 510 Composed Track Number if (FourFSPECOctets[Bit_Ops.Bit27] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 510:T"; I062DataItems[ItemIDToIndex("510")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("510")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 510:F"; I062DataItems[ItemIDToIndex("510")].CurrentlyPresent = false; } // 500 Estimated Accuracies if (FourFSPECOctets[Bit_Ops.Bit26] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 500:T"; I062DataItems[ItemIDToIndex("500")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("500")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 500:F"; I062DataItems[ItemIDToIndex("500")].CurrentlyPresent = false; } // 340 Measured Information if (FourFSPECOctets[Bit_Ops.Bit25] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 340:T"; I062DataItems[ItemIDToIndex("340")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("340")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " 340:F"; I062DataItems[ItemIDToIndex("340")].CurrentlyPresent = false; } break; // These are Reserved Expansion and Special Purpose fileds. case 5: // RE Reserved Expansion Field if (TheFifthFSPECOctet[Bit_Ops.Bit2] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " REF:T"; I062DataItems[ItemIDToIndex("REF")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("REF")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " REF:F"; I062DataItems[ItemIDToIndex("REF")].CurrentlyPresent = false; } // SP Special Purpose Indicator if (TheFifthFSPECOctet[Bit_Ops.Bit1] == true) { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " SPI:T"; I062DataItems[ItemIDToIndex("SPI")].HasBeenPresent = true; I062DataItems[ItemIDToIndex("SPI")].CurrentlyPresent = true; } else { DataOut[DataOutIndex] = DataOut[DataOutIndex] + " SPI:F"; I062DataItems[ItemIDToIndex("SPI")].CurrentlyPresent = false; } break; // Handle errors default: DataOut[DataOutIndex] = DataOut[DataOutIndex] + " UKN:T"; break; } } DataOutIndex++; CAT62DecodeAndStore.Do(LocalSingleRecordBuffer); DataBufferIndexForThisExtraction = DataBufferIndexForThisExtraction + CurrentDataBufferOctalIndex; } // Return decoded data NumOfMessagesDecoded = DataOutIndex; return(DataOut); }