public void Parse(WaveformConfigFileType file, RFmxInstrMX instr) { // Ensure CanParse was first called prior to executing this function if (rootData == null) { bool result = CanParse(file); if (!result) { throw new InvalidOperationException($"{file.FileName} is not a valid file for this plugin."); } } using (LogContext.PushProperty("Plugin", nameof(NrRfwsPlugin))) { // The RFWS file breaks up the NR configuration in two sections: a section representing carrier definitions (in which // the NR specific configurations are set), and then a all of the carrier sets in the waveform. These carrier sets // reference one of the carrier definitions and configure properties such as the frequency offset for the carrier. // // This doesn't neatly map to RFmx, so an extra step is performed after reading in these objects to then create // a unified object matching the RFmx layout. int carrierSetIndex = 0; List <RfwsCarrierSet> carrierSets = new List <RfwsCarrierSet>(); foreach (XElement carrierSetSection in rootData.FindSections <RfwsCarrierSet>()) { RfwsCarrierSet set = carrierSetSection.Deserialize <RfwsCarrierSet>(); carrierSets.Add(set); } List <Carrier> carriers = new List <Carrier>(); foreach (XElement carrierDefinitionSetion in rootData.FindSections <Carrier>()) { Carrier carrier = carrierDefinitionSetion.Deserialize <Carrier>(); carriers.Add(carrier); } // Now that we have loaded all relevant information from the file, construct the final object // and pass the data to the serialization engine to create the RFmx NR signal foreach (RfwsCarrierSet set in carrierSets) { NrSignalModel signal = new NrSignalModel(set, carriers); RFmxNRMX nrSignal = instr.CreateNRSignalConfigurationFromObject(signal, signalName: $"CarrierSet{carrierSetIndex}"); // Select initial measurements so RFmx doesn't complain on launch that nothing is selected nrSignal.SelectMeasurements("", RFmxNRMXMeasurementTypes.Acp | RFmxNRMXMeasurementTypes.ModAcc, true); // RFmx will complain in some configurations if this enabled; since the plugin identifes the RBs this uneeded nrSignal.SetAutoResourceBlockDetectionEnabled("", RFmxNRMXAutoResourceBlockDetectionEnabled.False); carrierSetIndex++; } } }
/// <summary> /// Constructs the unified signal model from an individual RFWS carrier set definition and the list of carriers /// that are included within that carrier set definition. /// </summary> /// <param name="set"></param> /// <param name="carriers"></param> public NrSignalModel(RfwsCarrierSet set, List <Carrier> carriers) { int numSubblocks = set.SubblockCarrierSettings.Max(s => (int)s.SubblockIndex) + 1; AutoIncrementCellId = set.AutoIncrementCellId; NumberOfSubblocks = numSubblocks; Subblocks = new List <Subblock>(numSubblocks); for (int i = 0; i < numSubblocks; i++) { // Get all component carriers for the current subblock iteration var currentSubblockSettings = set.SubblockCarrierSettings.Where(s => s.SubblockIndex == i); // The subblock properties are identical in each subblock configuration, so using the first is fine RfwsSubblockCarrierSettings settings = currentSubblockSettings.First(); // Since the RFWS file uses a flattened structure, there will be a separate subblock configuraiton object // for each component carriers. Since we have already filtered the list to select the currrent subblock, // the number of items now represents the number of component carriers within this subblock. int numComponentCarriers = currentSubblockSettings.Count(); Subblock subblock = new Subblock { CarrierSubblockOffset = settings.CarrierSubblockOffset, NumberOfComponentCarriers = numComponentCarriers, ComponentCarriers = new List <Carrier>(numComponentCarriers) }; for (int j = 0; j < numComponentCarriers; j++) { // Load the specific settings for the current component carrier that is being configured RfwsSubblockCarrierSettings currentCcSettings = currentSubblockSettings.Where(s => s.ComponentCarrierIndex == j).First(); // The object contains a CarrierDefinitionIndex field that describes which carrier definition it is using. // Since these may be used multiple times and certain properties may be changed depending on the configuration, // we clone the object so that we have a unique instance. Carrier associatedCarrier = carriers[(int)currentCcSettings.CarrierDefinitionIndex].ShallowCopy(); associatedCarrier.CarrierFrequencyOffset = currentCcSettings.CarrierFrequencyOffset; subblock.ComponentCarriers.Add(associatedCarrier); } Subblocks.Add(subblock); } }