From d83bdb986df1bff9a3cb5c8ad0eed7759362788f Mon Sep 17 00:00:00 2001 From: feyris-tan <4116042+feyris-tan@users.noreply.github.com> Date: Sat, 26 Jul 2025 19:16:19 +0200 Subject: [PATCH] Have DTOs for IQ Charts and RF Spectrum. --- Documentation/code_sample_build_iq.txt | 45 ++++++++++ .../code_sample_build_rf_spectrum.txt | 55 ++++++++++++ .../0x43_SatelliteDeliverySystemDescriptor.cs | 2 +- skyscraper8/Program.cs | 25 +++--- skyscraper8/Skyscraper/Drawing/IqChartData.cs | 73 ++++++++++++++++ .../Drawing/RfFrequencyChartData.cs | 84 +++++++++++++++++++ skyscraper8/Skyscraper/IO/StreamExtensions.cs | 9 ++ .../TunerFactoryConnectionManager.cs | 11 ++- 8 files changed, 291 insertions(+), 13 deletions(-) create mode 100644 Documentation/code_sample_build_iq.txt create mode 100644 Documentation/code_sample_build_rf_spectrum.txt create mode 100644 skyscraper8/Skyscraper/Drawing/IqChartData.cs create mode 100644 skyscraper8/Skyscraper/Drawing/RfFrequencyChartData.cs diff --git a/Documentation/code_sample_build_iq.txt b/Documentation/code_sample_build_iq.txt new file mode 100644 index 0000000..63f9a7a --- /dev/null +++ b/Documentation/code_sample_build_iq.txt @@ -0,0 +1,45 @@ +private static void IntegrationTest() +{ + TunerFactoryConnectionManager tunerConnectionManager = TunerFactoryConnectionManager.GetInstance(); + ITunerFactory tunerFactory = tunerConnectionManager.GetTunerFactoryById(2); + RemoteStreamReaderTunerFactory remoteTunerFactory = (RemoteStreamReaderTunerFactory)tunerFactory; + remoteTunerFactory.Hostname = "tetsuro"; + remoteTunerFactory.Port = 6970; + IStreamReader streamReader = remoteTunerFactory.CreateStreamReader(); + streamReader.CheckForDVBExEx((x, y, z) => Console.WriteLine("{0}, {1}, {2}", x, y, z.ToString())); + if (!streamReader.StartDvbEx(2)) + { + streamReader.Dispose(); + return; + } + DiSEqC_Opcode baseDiseqc = DiSEqC_Opcode.DISEQC_HIGH_NIBBLE | DiSEqC_Opcode.DISEQC_OPTION_A | DiSEqC_Opcode.DISEQC_POSITION_A; + DiSEqC_Opcode lh = baseDiseqc | DiSEqC_Opcode.DISEQC_LOW_BAND | DiSEqC_Opcode.DISEQC_HORIZONTAL; + int lof1 = 9750 * 1000; + int lof2 = 10600 * 1000; + int lofSw = 11700 * 1000; + int startFreq = 10700 * 1000; + int endFreq = 12750 * 1000; + int step = 1000; + + streamReader.SendDiSEqC(2, lh); + streamReader.SetChannel(11494000, 22000000, 0, VITERBIRATE_TYPE.VR_2_3, lof1, lof2, lofSw); + SearchResult sr = default(SearchResult); + streamReader.BLScanEx(11494000, 5000, 0, lof1, lof2, lofSw, 1000, STD_TYPE.STD_DVBS2, ref sr); + + sbyte[] buffer = new sbyte[200]; + IqChartData iq = IqChartData.Create(); + while (!iq.IsComplete) + { + if (!streamReader.IQScan(0, buffer, 100)) + throw new Exception("iq scan failed"); + iq.PushPacket(buffer); + } + + FileStream fs = File.OpenWrite("iq.bin"); + iq.SaveTo(fs); + fs.Flush(true); + fs.Close(); + + streamReader.StopDVB(); + streamReader.Dispose(); +} \ No newline at end of file diff --git a/Documentation/code_sample_build_rf_spectrum.txt b/Documentation/code_sample_build_rf_spectrum.txt new file mode 100644 index 0000000..f427551 --- /dev/null +++ b/Documentation/code_sample_build_rf_spectrum.txt @@ -0,0 +1,55 @@ +private static void IntegrationTest() +{ + TunerFactoryConnectionManager tunerConnectionManager = TunerFactoryConnectionManager.GetInstance(); + ITunerFactory tunerFactory = tunerConnectionManager.GetTunerFactoryById(2); + RemoteStreamReaderTunerFactory remoteTunerFactory = (RemoteStreamReaderTunerFactory)tunerFactory; + remoteTunerFactory.Hostname = "tetsuro"; + remoteTunerFactory.Port = 6970; + IStreamReader streamReader = remoteTunerFactory.CreateStreamReader(); + streamReader.CheckForDVBExEx((x, y, z) => Console.WriteLine("{0}, {1}, {2}", x, y, z.ToString())); + if (!streamReader.StartDvbEx(2)) + { + streamReader.Dispose(); + return; + } + DiSEqC_Opcode baseDiseqc = DiSEqC_Opcode.DISEQC_HIGH_NIBBLE | DiSEqC_Opcode.DISEQC_OPTION_A | DiSEqC_Opcode.DISEQC_POSITION_A; + DiSEqC_Opcode lh = baseDiseqc | DiSEqC_Opcode.DISEQC_LOW_BAND | DiSEqC_Opcode.DISEQC_HORIZONTAL; + DiSEqC_Opcode hh = baseDiseqc | DiSEqC_Opcode.DISEQC_HIGH_BAND | DiSEqC_Opcode.DISEQC_HORIZONTAL; + DiSEqC_Opcode lv = baseDiseqc | DiSEqC_Opcode.DISEQC_LOW_BAND | DiSEqC_Opcode.DISEQC_VERTICAL; + DiSEqC_Opcode hv = baseDiseqc | DiSEqC_Opcode.DISEQC_HIGH_BAND | DiSEqC_Opcode.DISEQC_VERTICAL; + int lof1 = 9750 * 1000; + int lof2 = 10600 * 1000; + int lofSw = 11700 * 1000; + int startFreq = 10700 * 1000; + int endFreq = 12750 * 1000; + int step = 1000; + + RfSpectrumData spectrumData = RfSpectrumData.Create(); + + void RunRfScan(RfSpectrumData spectrum, int startFreq, int endFreq, SatelliteDeliverySystemDescriptor.PolarizationEnum polarization, DiSEqC_Opcode diseqcCmd, int lof1, int lof2, int lofSw) + { + const int STEP = 1000; + streamReader.SendDiSEqC(2, diseqcCmd); + RfSpectrumDataBlock block = spectrumData.CreateBlock(startFreq, endFreq, STEP, polarization); + for (int i = startFreq; i <= endFreq; i += STEP) + { + double rf = Double.NaN; + streamReader.RFScan(i, diseqcCmd.HasFlag(DiSEqC_Opcode.DISEQC_HORIZONTAL) ? 0 : 1, lof1, lof2, lofSw, out rf); + Console.WriteLine("{0} {1}, {2}", i, polarization.ToString().Substring(0, 1), rf); + block.Push(i, rf); + } + } + + RunRfScan(spectrumData, startFreq, lofSw, SatelliteDeliverySystemDescriptor.PolarizationEnum.HorizontalLinear, lh,lof1,lof2,lofSw); + RunRfScan(spectrumData, lofSw, endFreq, SatelliteDeliverySystemDescriptor.PolarizationEnum.HorizontalLinear, hh, lof1, lof2, lofSw); + RunRfScan(spectrumData, startFreq, lofSw, SatelliteDeliverySystemDescriptor.PolarizationEnum.VerticalLinear, lv, lof1, lof2, lofSw); + RunRfScan(spectrumData, lofSw, endFreq, SatelliteDeliverySystemDescriptor.PolarizationEnum.VerticalLinear, hv, lof1, lof2, lofSw); + + FileStream fileStream = File.OpenWrite("spectrum.bin"); + spectrumData.SaveTo(fileStream); + fileStream.Flush(true); + fileStream.Close(); + + streamReader.StopDVB(); + streamReader.Dispose(); +} \ No newline at end of file diff --git a/skyscraper8/Dvb/Descriptors/0x43_SatelliteDeliverySystemDescriptor.cs b/skyscraper8/Dvb/Descriptors/0x43_SatelliteDeliverySystemDescriptor.cs index 4655591..604ea09 100644 --- a/skyscraper8/Dvb/Descriptors/0x43_SatelliteDeliverySystemDescriptor.cs +++ b/skyscraper8/Dvb/Descriptors/0x43_SatelliteDeliverySystemDescriptor.cs @@ -70,7 +70,7 @@ namespace skyscraper5.Dvb.Descriptors public long Frequency { get; set; } - public enum PolarizationEnum + public enum PolarizationEnum : byte { HorizontalLinear = 0, VerticalLinear = 1, diff --git a/skyscraper8/Program.cs b/skyscraper8/Program.cs index d661098..5a8bd9f 100644 --- a/skyscraper8/Program.cs +++ b/skyscraper8/Program.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; -using System.Runtime.InteropServices; +using log4net; using skyscraper5.Abertis; using skyscraper5.Hdmv; using skyscraper5.Mpeg2; @@ -21,15 +15,25 @@ using skyscraper5.Skyscraper.Scraper.FrameGrabber; using skyscraper5.Skyscraper.Scraper.Storage; using skyscraper5.Skyscraper.Scraper.Storage.Filesystem; using skyscraper5.Skyscraper.Scraper.Storage.InMemory; +using skyscraper5.Skyscraper.Scraper.StreamAutodetection; using skyscraper5.Skyscraper.Webserver; using skyscraper5.src.Aac; +using skyscraper5.src.Mpeg2.PacketFilter; using skyscraper5.src.Skyscraper.FrequencyListGenerator; using skyscraper5.T2MI; -using skyscraper5.src.Mpeg2.PacketFilter; using skyscraper8.Skyscraper.IO; -using log4net; -using skyscraper5.Skyscraper.Scraper.StreamAutodetection; using skyscraper8.Skyscraper.Scraper.Storage; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Configuration; +using System.Diagnostics; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using skyscraper5.Dvb.Descriptors; +using skyscraper8.Skyscraper.Drawing; [assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")] namespace skyscraper5 @@ -40,6 +44,7 @@ namespace skyscraper5 private static void IntegrationTest() { + } static void Main(string[] args) diff --git a/skyscraper8/Skyscraper/Drawing/IqChartData.cs b/skyscraper8/Skyscraper/Drawing/IqChartData.cs new file mode 100644 index 0000000..3d6995d --- /dev/null +++ b/skyscraper8/Skyscraper/Drawing/IqChartData.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using skyscraper5.Skyscraper.IO; + +namespace skyscraper8.Skyscraper.Drawing +{ + internal class IqChartData + { + private IqChartData() + { + IQ = new byte[256][]; + for (int i = 0; i < IQ.Length; i++) + { + IQ[i] = new byte[256]; + } + + packets = new List(); + } + + public byte[][] IQ; + private List packets; + private byte progress; + + public static IqChartData Create() + { + IqChartData child = new IqChartData(); + return child; + } + + public bool IsComplete { get; private set; } + + + public void PushPacket(sbyte[] buffer) + { + for (long l = 0; l < buffer.Length; l += 2) + { + byte i = (byte)buffer[l]; + byte q = (byte)buffer[l + 1]; + + if (IQ[i][q] != 255) + { + IQ[i][q]++; + if (IQ[i][q] > progress) + { + progress = IQ[i][q]; + Console.WriteLine(progress); + } + } + else + { + IsComplete = true; + } + } + + byte[] writableBuffer = Array.ConvertAll(buffer, x => (byte)x); + packets.Add(writableBuffer); + } + + public void SaveTo(FileStream fs) + { + fs.WriteUInt8(0x41); + foreach (byte[] packet in packets) + { + fs.WriteInt32LE(packet.Length); + fs.Write(packet, 0, packet.Length); + } + } + } +} diff --git a/skyscraper8/Skyscraper/Drawing/RfFrequencyChartData.cs b/skyscraper8/Skyscraper/Drawing/RfFrequencyChartData.cs new file mode 100644 index 0000000..8489af4 --- /dev/null +++ b/skyscraper8/Skyscraper/Drawing/RfFrequencyChartData.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using skyscraper5.Dvb.Descriptors; +using skyscraper5.Skyscraper.IO; + +namespace skyscraper8.Skyscraper.Drawing +{ + public class RfSpectrumData + { + + private RfSpectrumData() + { + blocks = new List(); + } + + public static RfSpectrumData Create() + { + RfSpectrumData child = new RfSpectrumData(); + return child; + } + + private List blocks; + + public RfSpectrumDataBlock CreateBlock(int minFreq, int maxFreq, int step, SatelliteDeliverySystemDescriptor.PolarizationEnum polarization) + { + RfSpectrumDataBlock child = new RfSpectrumDataBlock(minFreq,maxFreq,step,polarization); + blocks.Add(child); + return child; + } + + public void SaveTo(Stream stream) + { + foreach (RfSpectrumDataBlock block in blocks) + { + stream.WriteUInt8(0x58); + stream.WriteInt32LE(block.MinimumFrequency); + stream.WriteInt32LE(block.MaximumFrequency); + stream.WriteInt32LE(block.Step); + stream.WriteUInt8((byte)block.Polarization); + + double[] blockData = block.Data; + for (int i = 0; i < blockData.Length; i++) + stream.WriteFloat64LE(blockData[i]); + } + + stream.WriteUInt8(0x4f); + } + } + + public class RfSpectrumDataBlock + { + + public RfSpectrumDataBlock(int minFreq, int maxFreq, int step, SatelliteDeliverySystemDescriptor.PolarizationEnum polarization) + { + MinimumFrequency = minFreq; + MaximumFrequency = maxFreq; + Step = step; + Polarization = polarization; + Data = new double[Length + 1]; + } + + public SatelliteDeliverySystemDescriptor.PolarizationEnum Polarization { get; private set; } + + public int Step { get; private set; } + + public int MaximumFrequency { get; private set; } + + public int MinimumFrequency { get; private set; } + + public int Length => (MaximumFrequency - MinimumFrequency) / Step; + + public double[] Data { get; private set; } + + public void Push(int i, double rf) + { + i -= MinimumFrequency; + i /= Step; + Data[i] = rf; + } + } +} diff --git a/skyscraper8/Skyscraper/IO/StreamExtensions.cs b/skyscraper8/Skyscraper/IO/StreamExtensions.cs index 575b023..b091f0a 100644 --- a/skyscraper8/Skyscraper/IO/StreamExtensions.cs +++ b/skyscraper8/Skyscraper/IO/StreamExtensions.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Diagnostics; using System.IO; +using System.Net.Sockets; using System.Text; namespace skyscraper5.Skyscraper.IO @@ -284,5 +285,13 @@ namespace skyscraper5.Skyscraper.IO return result; } + public static void WriteFloat64LE(this Stream stream, double value) + { + byte[] buffer = BitConverter.GetBytes(value); + if (!BitConverter.IsLittleEndian) + Array.Reverse(buffer); + stream.Write(buffer, 0, 8); + } + } } diff --git a/skyscraper8/Skyscraper/IO/TunerInterface/TunerFactoryConnectionManager.cs b/skyscraper8/Skyscraper/IO/TunerInterface/TunerFactoryConnectionManager.cs index 82ef1eb..619b825 100644 --- a/skyscraper8/Skyscraper/IO/TunerInterface/TunerFactoryConnectionManager.cs +++ b/skyscraper8/Skyscraper/IO/TunerInterface/TunerFactoryConnectionManager.cs @@ -4,6 +4,7 @@ using System.Collections.ObjectModel; using System.Linq; using System.Runtime.Serialization; using skyscraper5.Skyscraper.Plugins; +using skyscraper8.Skyscraper.Plugins; namespace skyscraper5.Skyscraper.IO.TunerInterface { @@ -52,7 +53,13 @@ namespace skyscraper5.Skyscraper.IO.TunerInterface throw new NoTunerFactoryConfiguredException(); } - ReadOnlyCollection> readOnlyCollection = GetKnownFactories(); + return GetTunerFactoryById(neededFactory); + } + + public ITunerFactory GetTunerFactoryById(int neededFactory) + { + Ini ini = PluginManager.GetInstance().Ini; + ReadOnlyCollection> readOnlyCollection = GetKnownFactories(); foreach (var keyValuePair in readOnlyCollection) { if (keyValuePair.Key.Id == neededFactory) @@ -62,7 +69,7 @@ namespace skyscraper5.Skyscraper.IO.TunerInterface } } - throw new TunerFactoryNotFoundException(); + throw new PluginsException(String.Format("Tuner Factory {0} is not loaded.", neededFactory)); } }