├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── Binaries ├── Oscilloscope_1_0.zip └── Oscilloscope_1_1.zip ├── Docs ├── gnuplot.png ├── gui.png ├── oscilloscope.png └── speed_graph.png ├── Oscilloscope.sln ├── Oscilloscope ├── App.config ├── Channel.cs ├── GetterSetterAttribute.cs ├── GnuPlot.cs ├── Oscilloscope.cs ├── OscilloscopeCommands.cs ├── OscilloscopeEnum.cs ├── OscilloscopeLib.csproj ├── Properties │ └── AssemblyInfo.cs └── WaveForm.cs ├── OscilloscopeCLI ├── OscilloscopeCLI.csproj ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── app.config ├── OscilloscopeGUI ├── FrmMain.Designer.cs ├── FrmMain.cs ├── FrmMain.resx ├── OscilloscopeGUI.csproj ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ └── app.manifest ├── app.config └── oscilloscope.ico ├── OscilloscopeTest ├── OscilloscopeTest.cs ├── OscilloscopeTest.csproj └── Properties │ └── AssemblyInfo.cs └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: electro-logic 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /Binaries/Oscilloscope_1_0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/electro-logic/Oscilloscope/0e2c02bed0aebfc0c84ac1a4b7d9095409adec9f/Binaries/Oscilloscope_1_0.zip -------------------------------------------------------------------------------- /Binaries/Oscilloscope_1_1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/electro-logic/Oscilloscope/0e2c02bed0aebfc0c84ac1a4b7d9095409adec9f/Binaries/Oscilloscope_1_1.zip -------------------------------------------------------------------------------- /Docs/gnuplot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/electro-logic/Oscilloscope/0e2c02bed0aebfc0c84ac1a4b7d9095409adec9f/Docs/gnuplot.png -------------------------------------------------------------------------------- /Docs/gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/electro-logic/Oscilloscope/0e2c02bed0aebfc0c84ac1a4b7d9095409adec9f/Docs/gui.png -------------------------------------------------------------------------------- /Docs/oscilloscope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/electro-logic/Oscilloscope/0e2c02bed0aebfc0c84ac1a4b7d9095409adec9f/Docs/oscilloscope.png -------------------------------------------------------------------------------- /Docs/speed_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/electro-logic/Oscilloscope/0e2c02bed0aebfc0c84ac1a4b7d9095409adec9f/Docs/speed_graph.png -------------------------------------------------------------------------------- /Oscilloscope.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33530.505 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OscilloscopeTest", "OscilloscopeTest\OscilloscopeTest.csproj", "{38B8E55F-06FF-435F-8D4A-0967A9B94F4F}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OscilloscopeGUI", "OscilloscopeGUI\OscilloscopeGUI.csproj", "{ADFC469D-78BB-415D-AE23-B6F5D5A5BDFC}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OscilloscopeLib", "Oscilloscope\OscilloscopeLib.csproj", "{6BEA399D-CD60-4AF9-8499-3F720A5EDE80}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OscilloscopeCLI", "OscilloscopeCLI\OscilloscopeCLI.csproj", "{ECE2AD33-6CA7-43CA-9066-E9049D5D6FB0}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{55F7DD8E-BDDD-428C-8F7C-F214262EDAB8}" 15 | ProjectSection(SolutionItems) = preProject 16 | README.md = README.md 17 | EndProjectSection 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Release|Any CPU = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {38B8E55F-06FF-435F-8D4A-0967A9B94F4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {38B8E55F-06FF-435F-8D4A-0967A9B94F4F}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {38B8E55F-06FF-435F-8D4A-0967A9B94F4F}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {38B8E55F-06FF-435F-8D4A-0967A9B94F4F}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {ADFC469D-78BB-415D-AE23-B6F5D5A5BDFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {ADFC469D-78BB-415D-AE23-B6F5D5A5BDFC}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {ADFC469D-78BB-415D-AE23-B6F5D5A5BDFC}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {ADFC469D-78BB-415D-AE23-B6F5D5A5BDFC}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {6BEA399D-CD60-4AF9-8499-3F720A5EDE80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {6BEA399D-CD60-4AF9-8499-3F720A5EDE80}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {6BEA399D-CD60-4AF9-8499-3F720A5EDE80}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {6BEA399D-CD60-4AF9-8499-3F720A5EDE80}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {ECE2AD33-6CA7-43CA-9066-E9049D5D6FB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {ECE2AD33-6CA7-43CA-9066-E9049D5D6FB0}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {ECE2AD33-6CA7-43CA-9066-E9049D5D6FB0}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {ECE2AD33-6CA7-43CA-9066-E9049D5D6FB0}.Release|Any CPU.Build.0 = Release|Any CPU 41 | EndGlobalSection 42 | GlobalSection(SolutionProperties) = preSolution 43 | HideSolutionNode = FALSE 44 | EndGlobalSection 45 | GlobalSection(ExtensibilityGlobals) = postSolution 46 | SolutionGuid = {B7FD0580-0A90-440D-B243-287A11CC9982} 47 | EndGlobalSection 48 | EndGlobal 49 | -------------------------------------------------------------------------------- /Oscilloscope/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Oscilloscope/Channel.cs: -------------------------------------------------------------------------------- 1 | // Author: Leonardo Tazzini 2 | 3 | /// 4 | /// Represent an Oscilloscope Channel 5 | /// 6 | public class Channel 7 | { 8 | uint _channelID; 9 | Oscilloscope _oscilloscope; 10 | 11 | public Channel(uint channelID, Oscilloscope oscilloscope) 12 | { 13 | _channelID = channelID; 14 | _oscilloscope = oscilloscope; 15 | } 16 | // --------- Channel commands 17 | public OnOff GetBwLimit() 18 | { 19 | _oscilloscope.Write(":CHAN" + _channelID + ":BWLimit?"); 20 | return (OnOff)GetterSetterExtension.FromDescription(_oscilloscope.ReadString()); 21 | } 22 | public void SetBwLimit(OnOff value) 23 | { 24 | _oscilloscope.Write(":CHAN" + _channelID + ":BWLimit " + value.SetterDescription()); 25 | } 26 | // TODO: Coupling 27 | // TODO: Display 28 | // TODO: Invert 29 | public double GetOffset() 30 | { 31 | _oscilloscope.Write(":CHAN" + _channelID + ":OFFS?"); 32 | return double.Parse(_oscilloscope.ReadString()); 33 | } 34 | public void SetOffset(double value) 35 | { 36 | _oscilloscope.Write(":CHAN" + _channelID + ":OFFS " + value); 37 | } 38 | // TODO: Probe 39 | public double GetScale() 40 | { 41 | _oscilloscope.Write(":CHAN" + _channelID + ":SCAL?"); 42 | return double.Parse(_oscilloscope.ReadString()); 43 | } 44 | public void SetScale(double value) 45 | { 46 | _oscilloscope.Write(":CHAN" + _channelID + ":SCAL " + value); 47 | } 48 | public WaveForm GetWaveform() 49 | { 50 | _oscilloscope.Write(":WAVEFORM:DATA? CHAN" + _channelID); 51 | byte[] respose = _oscilloscope.Read(); 52 | 53 | long pointsCount = respose.Length - 10; 54 | 55 | double[] data = new double[pointsCount]; 56 | double[] times = new double[pointsCount]; 57 | 58 | double scale = GetScale(); 59 | double offset = GetOffset(); 60 | double oscTimeScale = _oscilloscope.GetTimebaseScale(); 61 | double oscTimeOffset = _oscilloscope.GetTimebaseOffset(); 62 | double sampleRate = _oscilloscope.GetAcquireSamplingRate(_channelID); 63 | 64 | double initial, interval; 65 | 66 | // 600 points 67 | //T(s) = ( - 1) * ( / 50) - [( * 6) - ] 68 | // > 600 points 69 | //T(s) = -[ ( - 10) / (1 / (2*)] 70 | 71 | if (pointsCount > 600) 72 | { 73 | initial = -((1.0 / sampleRate) * (pointsCount / 2)) + oscTimeOffset; 74 | interval = 1.0 / sampleRate; 75 | } 76 | else 77 | { 78 | initial = -(oscTimeScale * 6) - oscTimeOffset; 79 | interval = oscTimeScale / 50; 80 | } 81 | 82 | for (int i = 0; i < pointsCount; i++) 83 | { 84 | // Strip off 10 byte header and loop through data and termination characters 85 | int rawData = (int)respose[i + 10]; 86 | 87 | // Scale the vertical data from bytes to volts 88 | // A(V) = [(240 - ) * ( / 25) - [( + * 4.6)]] 89 | data[i] = ((240 - rawData) * scale / 25) - (offset + (scale * 4.6)); 90 | times[i] = initial + interval * i; 91 | } 92 | 93 | return new WaveForm(times, data); 94 | } 95 | 96 | // TODO: Filter 97 | // TODO: Vernier 98 | /// From DS1000E/D Waveform Data Formatting Guide 99 | /// 100 | public WaveForm GetWaveformString() 101 | { 102 | _oscilloscope.Write(":WAVEFORM:DATA? CHAN" + _channelID); 103 | string respose = _oscilloscope.ReadString(); 104 | 105 | long pointsCount = respose.Length - 10; 106 | 107 | //MessageBox.Show(pointsCount.ToString()); 108 | double[] data = new double[pointsCount]; 109 | double[] times = new double[pointsCount]; 110 | 111 | double scale = GetScale(); 112 | double offset = GetOffset(); 113 | double oscTimeScale = _oscilloscope.GetTimebaseScale(); 114 | double oscTimeOffset = _oscilloscope.GetTimebaseOffset(); 115 | double sampleRate = _oscilloscope.GetAcquireSamplingRate(_channelID); 116 | 117 | double initial, interval; 118 | 119 | // 600 points 120 | //T(s) = ( - 1) * ( / 50) - [( * 6) - ] 121 | // > 600 points 122 | //T(s) = -[ ( - 10) / (1 / (2*)] 123 | 124 | if (pointsCount > 600) 125 | { 126 | initial = -((1.0 / sampleRate) * (pointsCount / 2)) + oscTimeOffset; 127 | interval = 1.0 / sampleRate; 128 | } 129 | else 130 | { 131 | initial = -(oscTimeScale * 6) - oscTimeOffset; 132 | interval = oscTimeScale / 50; 133 | } 134 | 135 | for (int i = 0; i < pointsCount; i++) 136 | { 137 | // Strip off 10 byte header and loop through data and termination characters 138 | int rawData = (int)respose[i + 10]; 139 | 140 | // Scale the vertical data from bytes to volts 141 | // A(V) = [(240 - ) * ( / 25) - [( + * 4.6)]] 142 | data[i] = ((240 - rawData) * scale / 25) - (offset + (scale * 4.6)); 143 | //data[i] = rawData; 144 | 145 | times[i] = initial + interval * i; 146 | } 147 | 148 | return new WaveForm(times, data); 149 | } 150 | } -------------------------------------------------------------------------------- /Oscilloscope/GetterSetterAttribute.cs: -------------------------------------------------------------------------------- 1 | // Author: Leonardo Tazzini 2 | 3 | using System; 4 | 5 | [AttributeUsage(AttributeTargets.Field)] 6 | /// 7 | /// An attribute that can be applied to fields (like enum fields) and add two string descriptions called getter and setter 8 | /// 9 | public class GetterSetterAttribute : Attribute 10 | { 11 | public string Getter { get; set; } 12 | public string Setter { get; set; } 13 | 14 | public GetterSetterAttribute(string getter_setter) 15 | { 16 | Getter = Setter = getter_setter; 17 | } 18 | public GetterSetterAttribute(string getter, string setter) 19 | { 20 | Getter = getter; 21 | Setter = setter; 22 | } 23 | } 24 | 25 | public static class GetterSetterExtension 26 | { 27 | /// 28 | /// Return Getter description from an enum marked with GetterSetterAttribute, otherwise the enum value 29 | /// 30 | public static string GetterDescription(this Enum value) 31 | { 32 | var getterSetterAttributes = (GetterSetterAttribute[])(value.GetType().GetField(value.ToString())).GetCustomAttributes(typeof(GetterSetterAttribute), false); 33 | return getterSetterAttributes.Length > 0 ? getterSetterAttributes[0].Getter : value.ToString(); 34 | } 35 | 36 | /// 37 | /// Return Setter description from an enum marked with GetterSetterAttribute, otherwise the enum value 38 | /// 39 | public static string SetterDescription(this Enum value) 40 | { 41 | var getterSetterAttributes = (GetterSetterAttribute[])(value.GetType().GetField(value.ToString())).GetCustomAttributes(typeof(GetterSetterAttribute), false); 42 | return getterSetterAttributes.Length > 0 ? getterSetterAttributes[0].Setter : value.ToString(); 43 | } 44 | 45 | /// 46 | /// Return Enum with description that correspond to GetterSetterAttribute 47 | /// 48 | public static Enum FromDescription(string description) 49 | { 50 | foreach (Enum item in Enum.GetValues(typeof(T))) 51 | { 52 | if (item.GetterDescription() == description) 53 | { 54 | return item; 55 | } 56 | } 57 | throw new Exception("Enum not found: [" + description + "]"); 58 | } 59 | } -------------------------------------------------------------------------------- /Oscilloscope/GnuPlot.cs: -------------------------------------------------------------------------------- 1 | // Author: Leonardo Tazzini 2 | 3 | using System; 4 | using System.Diagnostics; 5 | using System.Drawing; 6 | using System.IO; 7 | using System.Windows.Forms; 8 | 9 | /// 10 | /// Tested with Gnuplot 5.2 11 | /// 12 | public class GnuPlot 13 | { 14 | public GnuPlot() 15 | { 16 | // Default path for gnuplot 17 | this.Path = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "gnuplot\\bin\\gnuplot.exe"); 18 | // TODO: Check if path is valid 19 | } 20 | 21 | public GnuPlot(string path) 22 | { 23 | this.Path = path; 24 | } 25 | 26 | /// 27 | /// Path of gnuplot.exe 28 | /// 29 | public string Path { get; set; } 30 | 31 | /// 32 | /// Graph input CSV with GnuPlot. NumWaves is the number of channels to draw. If imageOut a PNG image is saved into out.png and displayed. 33 | /// 34 | public void DrawGraph(string csvFileName, int numWaves, bool generatePngImage = true) 35 | { 36 | // gnuplot.exe not found 37 | if(!File.Exists(Path)) 38 | { 39 | MessageBox.Show("gnuplot.exe not found. Please check the path."); 40 | return; 41 | } 42 | 43 | var gnuPlot = new Process(); 44 | gnuPlot.StartInfo.FileName = Path; 45 | gnuPlot.StartInfo.CreateNoWindow = true; 46 | gnuPlot.StartInfo.UseShellExecute = false; 47 | gnuPlot.StartInfo.RedirectStandardInput = true; 48 | gnuPlot.Start(); 49 | 50 | StreamWriter gnuPlotSw = gnuPlot.StandardInput; 51 | if (generatePngImage) 52 | { 53 | // TODO: Remove dependency from Windows Forms 54 | Rectangle bounds = Screen.PrimaryScreen.WorkingArea; 55 | gnuPlotSw.WriteLine("set terminal png size " + (bounds.Width * 0.9) + "," + (bounds.Height * 0.8)); 56 | gnuPlotSw.WriteLine("set out 'out.png'"); 57 | } 58 | gnuPlotSw.WriteLine("set style data lines"); //linespoints 59 | gnuPlotSw.WriteLine("set datafile separator ';'"); 60 | //gnuPlotSw.WriteLine("set decimalsign locale; set decimalsign ','"); 61 | gnuPlotSw.WriteLine("set xlabel 'time (s)'"); 62 | gnuPlotSw.WriteLine("set ylabel 'value (v)'"); 63 | gnuPlotSw.WriteLine("set grid"); 64 | //gnuPlotSw.WriteLine("set xtics 0,0.5"); 65 | //gnuPlotSw.WriteLine("set ytics 0,5"); 66 | 67 | // TODO: evaluate add "every .." to gnuplot cmd line 68 | gnuPlotSw.Write("plot '" + System.IO.Path.GetFullPath(csvFileName) + "' using 1:2 title 'CH1'"); 69 | if (numWaves == 2) 70 | gnuPlotSw.WriteLine(", '' using 1:3 title 'CH2'"); 71 | else 72 | gnuPlotSw.Write("\n"); 73 | gnuPlotSw.Flush(); 74 | if (generatePngImage) 75 | { 76 | gnuPlotSw.WriteLine("exit"); 77 | gnuPlotSw.Flush(); 78 | gnuPlot.WaitForExit(); 79 | Process.Start("out.png"); 80 | } 81 | gnuPlot.Close(); 82 | } 83 | } -------------------------------------------------------------------------------- /Oscilloscope/Oscilloscope.cs: -------------------------------------------------------------------------------- 1 | // Author: Leonardo Tazzini 2 | 3 | using NationalInstruments.Visa; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.Linq; 8 | using System.Threading; 9 | 10 | /// 11 | /// Handle Rigol's Oscilloscopes like model DS1102E 12 | /// 13 | public partial class Oscilloscope : IDisposable 14 | { 15 | string _model; 16 | string _serialNumber; 17 | string _swVersion; 18 | Channel[] _channels; 19 | uint _numChannels; // 2 Channel models like DS1102E 20 | 21 | MessageBasedSession _mbSession; 22 | static ResourceManager _resManager = new ResourceManager(); 23 | bool _isDisposed; 24 | 25 | // TODO: Move in VisaHelper file 26 | public static string[] GetResources() 27 | { 28 | string[] results = new string[] { }; 29 | try 30 | { 31 | results = _resManager.Find("?*").ToArray(); 32 | } 33 | catch (Exception ex) 34 | { 35 | Debug.WriteLine(ex); 36 | } 37 | return results; 38 | } 39 | public Oscilloscope(string resource = "USB?*DS1E?*INSTR", uint channels = 2) 40 | { 41 | // TODO: check if channels is valid 42 | _numChannels = channels; 43 | _channels = new Channel[_numChannels]; 44 | 45 | // Create Message based session, open first resource found 46 | _mbSession = (MessageBasedSession)_resManager.Open(_resManager.Find(resource).First()); 47 | _mbSession.TimeoutMilliseconds = 1000 * 60 * 5; 48 | 49 | // Create channel object for every physical channel of oscilloscope 50 | for (uint i = 0; i < _numChannels; i++) 51 | { 52 | _channels[i] = new Channel(i + 1, this); 53 | } 54 | 55 | Write("*IDN?"); 56 | // Example response: Rigol Technologies,DS1102E,DS1EB1XXXXXXXX,00.02.06.00.01 57 | string[] fields = ReadString().Split(','); 58 | _model = fields[1]; 59 | _serialNumber = fields[2]; 60 | _swVersion = fields[3]; 61 | } 62 | public Channel[] Channels 63 | { 64 | get => _channels; 65 | set => _channels = value; 66 | } 67 | public Channel Channel1 => _channels[0]; 68 | public Channel Channel2 => _channels[1]; 69 | /// 70 | /// Return Waveforms of Channel1 and Channel2 71 | /// 72 | public WaveForm GetWaveforms() 73 | { 74 | // TODO: Improve for 4 channel model 75 | WaveForm wave1 = Channel1.GetWaveform(); 76 | WaveForm wave2 = Channel2.GetWaveform(); 77 | return new WaveForm(wave1.Times, new List() { wave1.Values[0], wave2.Values[0] }); 78 | } 79 | public string Model => _model; 80 | public string SerialNumber => _serialNumber; 81 | public string SwVersion=>_swVersion; 82 | public void Write(string str) 83 | { 84 | _mbSession.RawIO.Write(str); 85 | // Give time to process command 86 | Thread.Sleep(50); 87 | // TODO: Improve and validate 88 | } 89 | public string ReadString() 90 | { 91 | // Read the response; omit end-of-line characters. 92 | return _mbSession.RawIO.ReadString().TrimEnd( '\r', '\n'); 93 | } 94 | public byte[] Read() 95 | { 96 | // Rigol DS1102E Long Memory can acquire 1M points (1048576 bytes + 10 bytes header) 97 | var readBytes = _mbSession.RawIO.Read(1048586, out var status); 98 | Debug.WriteLine(string.Format("Readed {0} bytes from device with Status {1}", readBytes.Length, status)); 99 | return readBytes; 100 | } 101 | /// 102 | /// Wait until Trigger Status is Stop 103 | /// 104 | /// 105 | /// Poll every 50ms 106 | /// 107 | public void WaitTriggerStop() 108 | { 109 | while (GetTriggerStatus() != TriggerStatus.Stop) 110 | { 111 | Thread.Sleep(50); 112 | } 113 | } 114 | protected virtual void Dispose(bool disposing) 115 | { 116 | if (!_isDisposed) 117 | { 118 | if (disposing) 119 | { 120 | _mbSession.Dispose(); 121 | } 122 | _isDisposed = true; 123 | } 124 | } 125 | public void Dispose() 126 | { 127 | // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method 128 | Dispose(disposing: true); 129 | GC.SuppressFinalize(this); 130 | } 131 | // See OscilloscopeCommands for commands like Run, Stop, Get/Set Property, etc.. 132 | } -------------------------------------------------------------------------------- /Oscilloscope/OscilloscopeCommands.cs: -------------------------------------------------------------------------------- 1 | // Author: Leonardo Tazzini 2 | 3 | using System; 4 | 5 | public partial class Oscilloscope 6 | { 7 | // --------- System Commands 8 | 9 | /// 10 | /// The command initiates the oscilloscope to acquire waveform data according to its current settings. 11 | /// Acquisition runs continuously until the oscilloscope receives a STOP command. 12 | /// 13 | public void Run() 14 | { 15 | Write(":RUN"); 16 | } 17 | 18 | /// 19 | /// The command resets the system parameters. 20 | /// 21 | public void Reset() 22 | { 23 | Write("*RST"); 24 | } 25 | 26 | /// 27 | /// The command controls the oscilloscope to stop acquiring data. To restart the acquisition, use the RUN command. 28 | /// 29 | public void Stop() 30 | { 31 | Write(":STOP"); 32 | } 33 | 34 | /// 35 | /// The command controls the oscilloscope to evaluate all input waveforms characteristics and set the optimum conditions to display the waveforms. 36 | /// 37 | public void Auto() 38 | { 39 | Write(":AUTO"); 40 | } 41 | 42 | /// 43 | /// The command is to extract the current information on the screen and save the bitmap into the U disc in the form of “HardCopyxxx.bmp”. 44 | /// 45 | /// 46 | /// This command is unavailable in file system 47 | /// 48 | public void HardCopy() 49 | { 50 | Write(":HARDcopy"); 51 | } 52 | 53 | // --------- Acquire commands 54 | 55 | /// 56 | /// Query current acquire type of the oscilloscope. 57 | /// 58 | public AcquireType GetAcquireType() 59 | { 60 | Write(":ACQ:TYPE?"); 61 | return (AcquireType)GetterSetterExtension.FromDescription(ReadString()); 62 | } 63 | 64 | /// 65 | /// Set current acquire type of the oscilloscope. 66 | /// 67 | public void SetAcquireType(AcquireType memoryDepth) 68 | { 69 | 70 | Write(":ACQ:TYPE " + memoryDepth.SetterDescription()); 71 | } 72 | 73 | /// 74 | /// Query current acquire mode of the oscilloscope. 75 | /// 76 | public AcquireMode GetAcquireMode() 77 | { 78 | Write(":ACQuire:MODE?"); 79 | return (AcquireMode)GetterSetterExtension.FromDescription(ReadString()); 80 | } 81 | 82 | /// 83 | /// Set current acquire mode of the oscilloscope. 84 | /// 85 | public void SetAcquireMode(AcquireMode memoryDepth) 86 | { 87 | Write(":ACQuire:MODE " + memoryDepth.SetterDescription()); 88 | } 89 | 90 | /// 91 | /// Query average numbers in Average mode. 92 | /// 93 | public AcquireAverages GetAcquireAverages() 94 | { 95 | Write(":ACQuire:AVERages?"); 96 | return (AcquireAverages)GetterSetterExtension.FromDescription(ReadString()); 97 | } 98 | 99 | /// 100 | /// Set average numbers in Average mode. 101 | /// 102 | public void SetAcquireAverages(AcquireAverages acquireAverage) 103 | { 104 | Write(":ACQuire:AVERages " + acquireAverage.SetterDescription()); 105 | } 106 | 107 | /// 108 | /// Queries the current sampling rate of the analog channel or digital channel (only for DS1000D series). is 1 or 2 means channel 1 or channel 2. 109 | /// 110 | public double GetAcquireSamplingRate(uint channel) 111 | { 112 | if (channel > _numChannels) 113 | { 114 | throw new ArgumentException("Wrong channel"); 115 | } 116 | // TODO: Digital channel of DS1000D not supported 117 | Write(":ACQuire:SAMPlingrate? CHANnel" + channel); 118 | return double.Parse(ReadString()); 119 | } 120 | 121 | /// 122 | /// Query the memory depth of the oscilloscope. 123 | /// 124 | public AcquireMemoryDepth GetAcquireMemoryDepth() 125 | { 126 | Write(":ACQuire:MEMDepth?"); 127 | return (AcquireMemoryDepth)GetterSetterExtension.FromDescription(ReadString()); 128 | } 129 | 130 | /// 131 | /// Set the memory depth of the oscilloscope. 132 | /// 133 | public void SetAcquireMemoryDepth(AcquireMemoryDepth memoryDepth) 134 | { 135 | Write(":ACQuire:MEMDepth " + memoryDepth.SetterDescription()); 136 | } 137 | 138 | // --------- Display commands 139 | // TODO 140 | 141 | // --------- Timebase commands 142 | 143 | /// 144 | /// Query scan mode of horizontal timebase 145 | /// 146 | public TimebaseMode GetTimebaseMode() 147 | { 148 | Write(":TIMebase:MODE?"); 149 | return (TimebaseMode)GetterSetterExtension.FromDescription(ReadString()); 150 | } 151 | 152 | /// 153 | /// Set scan mode of horizontal timebase 154 | /// 155 | public void SetTimebaseMode(TimebaseMode value) 156 | { 157 | Write(":TIMebase:MODE " + value.SetterDescription()); 158 | } 159 | 160 | /// 161 | /// Query the offset of the MAIN or DELayed timebase 162 | /// (that is offset of the waveform position relative to the trigger midpoint.). 163 | /// In NORMAL mode, the range of is 1s ~ end of the memory; 164 | /// In STOP mode, the range of is -500s ~ +500s; 165 | /// In SCAN mode, the range of is -6*Scale ~ +6*Scale; (Note: Scale indicates the current horizontal scale, the unit is s/div.) 166 | /// In MAIN state, the item [:DELayed] should be omitted. 167 | /// 168 | public double GetTimebaseOffset() 169 | { 170 | // TODO: Delayed option 171 | Write(":TIMebase:OFFS?"); 172 | return double.Parse(ReadString()); 173 | } 174 | 175 | /// 176 | /// Set the offset of the MAIN or DELayed timebase 177 | /// 178 | public void SetTimebaseOffset(double value) 179 | { 180 | // TODO: Delayed option 181 | Write(":TIMebase:OFFSet " + value); 182 | } 183 | 184 | /// 185 | /// Query the horizontal scale for MAIN or DELayed timebase, the unit is s/div (seconds/grid), thereinto: 186 | /// In YT mode, the range of is 2ns - 50s; 187 | /// In ROLL mode, the range of is 500ms - 50s; 188 | /// In MAIN state, the item [:DELayed] should be omitted. 189 | /// 190 | public double GetTimebaseScale() 191 | { 192 | // TODO: Delayed option 193 | Write(":TIMebase:SCALe?"); 194 | return double.Parse(ReadString()); 195 | } 196 | 197 | /// 198 | /// Set the horizontal scale for MAIN or DELayed timebase, the unit is s/div (seconds/grid) 199 | /// 200 | public void SetTimebaseScale(double value) 201 | { 202 | // TODO: Delayed option 203 | Write(":TIMebase:SCALe " + value); 204 | } 205 | 206 | 207 | /// 208 | /// Query the horizontal timebase 209 | /// 210 | public TimebaseFormat GetTimebaseFormat() 211 | { 212 | // TODO: Delayed option 213 | Write(":TIMebase:FORMat?"); 214 | return (TimebaseFormat)GetterSetterExtension.FromDescription(ReadString()); 215 | } 216 | 217 | /// 218 | /// Set the horizontal timebase 219 | /// 220 | public void SetTimebaseFormat(TimebaseFormat value) 221 | { 222 | // TODO: Delayed option 223 | Write(":TIMebase:FORMat " + value.SetterDescription()); 224 | } 225 | 226 | // --------- Trigger commands 227 | 228 | // TODO: Complete 229 | 230 | /// 231 | /// Queries the operating status of the oscilloscope. The status could be RUN, STOP, T`D, WAIT or AUTO 232 | /// 233 | public TriggerStatus GetTriggerStatus() 234 | { 235 | Write(":TRIGger:STATus?"); 236 | return (TriggerStatus)GetterSetterExtension.FromDescription(ReadString()); 237 | } 238 | 239 | public TriggerSweep GetTriggerSweep() 240 | { 241 | Write(":TRIGger:EDGE:SWEep?"); 242 | return (TriggerSweep)GetterSetterExtension.FromDescription(ReadString()); 243 | } 244 | 245 | public void SetTriggerSweep(TriggerSweep memoryDepth) 246 | { 247 | Write(":TRIGger:EDGE:SWEep " + memoryDepth.SetterDescription()); 248 | } 249 | 250 | /// 251 | /// Sets the trigger level to the vertical midpoint of amplitude. 252 | /// 253 | public void TriggerHalf() 254 | { 255 | Write(":Trig%50"); 256 | } 257 | 258 | /// 259 | /// Forces the oscilloscope to trigger signal, which is usually used in “Normal” and “Single” mode. 260 | /// 261 | public void TriggerForce() 262 | { 263 | Write(":FORCetrig"); 264 | } 265 | 266 | // --------- Storage commands (uncomment to enable it) 267 | 268 | /// 269 | /// Recalls the system settings before leaving factory. 270 | /// 271 | //public void StorageFactoryLoad() 272 | //{ 273 | // Write(":STORage:FACTory:LOAD"); 274 | //} 275 | 276 | // --------- Math commands 277 | 278 | /// 279 | /// Query the On/Off state of the math operation 280 | /// 281 | public OnOff GetMathDisplay() 282 | { 283 | Write(":MATH:DISPlay?"); 284 | return (OnOff)GetterSetterExtension.FromDescription(ReadString()); 285 | } 286 | 287 | /// 288 | /// Set the On/Off state of the math operation 289 | /// 290 | public void SetMathDisplay(OnOff display) 291 | { 292 | Write(":MATH:DISPlay " + display.SetterDescription()); 293 | } 294 | 295 | // --------- Measure commands 296 | 297 | // --------- Waveform commands 298 | 299 | // :WAVeform:DATA? is in GetWaveform() in Channel class 300 | 301 | /// 302 | /// Query mode of waveform points 303 | /// 304 | public PointsMode GetWaveformPointsMode() 305 | { 306 | Write(":WAVeform:POINts:MODE?"); 307 | return (PointsMode)GetterSetterExtension.FromDescription(ReadString()); 308 | } 309 | 310 | /// 311 | /// Set mode of waveform points 312 | /// 313 | public void SetWaveformPointsMode(PointsMode value) 314 | { 315 | Write(":WAVeform:POINts:MODE " + value.SetterDescription()); 316 | } 317 | 318 | // --------- LA commands 319 | // --------- Key commands 320 | 321 | /// 322 | /// The command unlocks the remote control. 323 | /// 324 | public void Close() 325 | { 326 | Write(":KEY:FORCE"); 327 | } 328 | 329 | } -------------------------------------------------------------------------------- /Oscilloscope/OscilloscopeEnum.cs: -------------------------------------------------------------------------------- 1 | // Author: Leonardo Tazzini 2 | 3 | // Enumerations used by Oscilloscope annotated with GetterSetterAttribute 4 | 5 | public enum OnOff 6 | { 7 | [GetterSetterAttribute("ON")] 8 | On, 9 | [GetterSetterAttribute("OFF")] 10 | Off 11 | } 12 | 13 | // --------- Acquire enums 14 | 15 | public enum AcquireType 16 | { 17 | [GetterSetterAttribute("NORMAL")] 18 | Normal, 19 | [GetterSetterAttribute("AVERAGE")] 20 | Average, 21 | [GetterSetterAttribute("Peak Detect", "PEAKDETECT")] 22 | PeakDetect 23 | } 24 | 25 | public enum AcquireMode 26 | { 27 | [GetterSetterAttribute("REAL_TIME", "RTIM")] 28 | RealTime, 29 | [GetterSetterAttribute("EQUAL_TIME", "ETIM")] 30 | EquiTime 31 | } 32 | 33 | public enum AcquireAverages 34 | { 35 | [GetterSetterAttribute("2")] 36 | Average2, 37 | [GetterSetterAttribute("4")] 38 | Average4, 39 | [GetterSetterAttribute("8")] 40 | Average8, 41 | [GetterSetterAttribute("16")] 42 | Average16, 43 | [GetterSetterAttribute("32")] 44 | Average32, 45 | [GetterSetterAttribute("64")] 46 | Average64, 47 | [GetterSetterAttribute("128")] 48 | Average128, 49 | [GetterSetterAttribute("256")] 50 | Average256 51 | } 52 | 53 | public enum AcquireMemoryDepth 54 | { 55 | [GetterSetterAttribute("NORMAL")] 56 | Normal, 57 | [GetterSetterAttribute("LONG")] 58 | Long 59 | } 60 | 61 | // --------- Display enums 62 | 63 | public enum DisplayType 64 | { 65 | [GetterSetterAttribute("VECTORS")] 66 | Vectors, 67 | [GetterSetterAttribute("DOTS")] 68 | Dots 69 | } 70 | 71 | public enum DisplayGrid 72 | { 73 | [GetterSetterAttribute("FULL")] 74 | Full, 75 | [GetterSetterAttribute("HALF")] 76 | Half, 77 | [GetterSetterAttribute("NONE")] 78 | None 79 | } 80 | 81 | public enum DisplayMenu 82 | { 83 | [GetterSetterAttribute("1s", "1")] 84 | One, 85 | [GetterSetterAttribute("2s", "2")] 86 | Two, 87 | [GetterSetterAttribute("5s", "5")] 88 | Five, 89 | [GetterSetterAttribute("10s", "10")] 90 | Ten, 91 | [GetterSetterAttribute("20s", "20")] 92 | Twelve, 93 | [GetterSetterAttribute("Infinite", "Infinite")] 94 | Infinite 95 | } 96 | 97 | // --------- Timebase enums 98 | 99 | public enum TimebaseMode 100 | { 101 | [GetterSetterAttribute("MAIN")] 102 | Main, 103 | [GetterSetterAttribute("DELAYED")] 104 | Delayed 105 | } 106 | 107 | public enum TimebaseFormat 108 | { 109 | [GetterSetterAttribute("X-Y", "XY")] 110 | XY, 111 | [GetterSetterAttribute("Y-T", "YT")] 112 | YT, 113 | [GetterSetterAttribute("SCANNING")] 114 | Scanning 115 | } 116 | 117 | // --------- Trigger enums 118 | 119 | public enum TriggerMode 120 | { 121 | [GetterSetterAttribute("EDGE")] 122 | Edge, 123 | [GetterSetterAttribute("PULS")] 124 | Pulse, 125 | [GetterSetterAttribute("VIDEO")] 126 | Video, 127 | [GetterSetterAttribute("SLOP")] 128 | Slope, 129 | [GetterSetterAttribute("PATT")] 130 | Pattern, 131 | [GetterSetterAttribute("DUR")] 132 | Duration, 133 | [GetterSetterAttribute("ALT")] 134 | Alternation 135 | } 136 | 137 | public enum TriggerSource 138 | { 139 | [GetterSetterAttribute("CHAN1")] 140 | Channel1, 141 | [GetterSetterAttribute("CHAN2")] 142 | Channel2, 143 | [GetterSetterAttribute("EXT")] 144 | External, 145 | [GetterSetterAttribute("ACL")] 146 | ACLine, 147 | [GetterSetterAttribute("DIG")] 148 | Digital 149 | } 150 | 151 | public enum TriggerSweep 152 | { 153 | [GetterSetterAttribute("AUTO")] 154 | Auto, 155 | [GetterSetterAttribute("NORMAL")] 156 | Normal, 157 | [GetterSetterAttribute("SINGLE")] 158 | Single 159 | } 160 | 161 | public enum TriggerCoupling 162 | { 163 | /// 164 | /// Allow all signals pass. 165 | /// 166 | [GetterSetterAttribute("DC")] 167 | DC, 168 | /// 169 | /// Block DC signals and attenuate the signals lower than 10Hz. 170 | /// 171 | [GetterSetterAttribute("AC")] 172 | AC, 173 | /// 174 | /// Reject high frequency signals (Higher than 150KHz). 175 | /// 176 | [GetterSetterAttribute("HF")] 177 | HF, 178 | /// 179 | /// Reject DC signals and attenuate low frequency signals (Lower than 8KHz). 180 | /// 181 | [GetterSetterAttribute("LF")] 182 | LF 183 | } 184 | 185 | public enum TriggerStatus 186 | { 187 | [GetterSetterAttribute("RUN")] 188 | Run, 189 | [GetterSetterAttribute("STOP")] 190 | Stop, 191 | [GetterSetterAttribute("T'D")] 192 | TD, 193 | [GetterSetterAttribute("WAIT")] 194 | Wait, 195 | [GetterSetterAttribute("AUTO")] 196 | Auto 197 | } 198 | 199 | // --------- Math enums 200 | 201 | public enum MathOperate 202 | { 203 | [GetterSetterAttribute("A+B")] 204 | AplusB, 205 | [GetterSetterAttribute("A-B")] 206 | AminusB, 207 | [GetterSetterAttribute("AB")] 208 | AB, 209 | [GetterSetterAttribute("FFT")] 210 | FFT 211 | } 212 | 213 | // --------- Wavewform enums 214 | 215 | public enum PointsMode 216 | { 217 | [GetterSetterAttribute("NORMAL")] 218 | Normal, 219 | [GetterSetterAttribute("MAXIMUM")] 220 | Maximum, 221 | [GetterSetterAttribute("RAW")] 222 | Raw 223 | } -------------------------------------------------------------------------------- /Oscilloscope/OscilloscopeLib.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6BEA399D-CD60-4AF9-8499-3F720A5EDE80} 8 | Library 9 | Properties 10 | OscilloscopeLib 11 | OscilloscopeLib 12 | v4.8 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | false 25 | latest 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | false 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 70 | -------------------------------------------------------------------------------- /Oscilloscope/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Oscilloscope")] 9 | [assembly: AssemblyProduct("Oscilloscope")] 10 | [assembly: AssemblyCopyright("Copyright © Leonardo Tazzini 2014")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("cf7bc634-6bac-4f72-a351-0e514899eacc")] 19 | 20 | // Version information for an assembly consists of the following four values: 21 | // 22 | // Major Version 23 | // Minor Version 24 | // Build Number 25 | // Revision 26 | // 27 | // You can specify all the values or you can default the Build and Revision Numbers 28 | // by using the '*' as shown below: 29 | // [assembly: AssemblyVersion("1.0.*")] 30 | [assembly: AssemblyVersion("1.1.0.0")] 31 | [assembly: AssemblyFileVersion("1.1.0.0")] 32 | -------------------------------------------------------------------------------- /Oscilloscope/WaveForm.cs: -------------------------------------------------------------------------------- 1 | // Author: Leonardo Tazzini 2 | 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | /// 9 | /// Represent an Oscilloscope WaveForm composed by a list of Times and a list of one or more Values (if waveform contains multiple channels) 10 | /// 11 | public class WaveForm 12 | { 13 | double[] _times; 14 | List _values; 15 | 16 | public WaveForm(double[] times, List values) 17 | { 18 | _times = times; 19 | _values = values; 20 | } 21 | 22 | public WaveForm(double[] times, double[] values) 23 | { 24 | _times = times; 25 | _values = new List(); 26 | _values.Add(values); 27 | } 28 | 29 | public double[] Times 30 | { 31 | get { return _times; } 32 | set { _times = value; } 33 | } 34 | 35 | public List Values 36 | { 37 | get { return _values; } 38 | set { _values = value; } 39 | } 40 | 41 | /// 42 | /// Save Waveform in a CSV (Comma Separated Values) file separated by semicolon 43 | /// 44 | public void SaveCSV(string fileName) 45 | { 46 | StringBuilder sb = new StringBuilder(_times.Length * 10); 47 | 48 | int valuesCount = _values.Count; 49 | int timesCount = _times.Count(); 50 | 51 | // Header 52 | sb.Append("TIME(s);"); 53 | for (int j = 1; j < valuesCount + 1; j++) 54 | { 55 | sb.Append("CH"); 56 | sb.Append(j); 57 | sb.Append("(v);"); 58 | } 59 | sb.Append("\n"); 60 | 61 | // Data 62 | for (int i = 0; i < timesCount; i++) 63 | { 64 | sb.Append(_times[i]); 65 | sb.Append(";"); 66 | for (int j = 0; j < valuesCount; j++) 67 | { 68 | sb.Append(_values[j][i]); 69 | sb.Append(";"); 70 | } 71 | sb.Append("\n"); 72 | } 73 | 74 | //sb = sb.Replace('.', ','); // Excel ITA compatibility 75 | File.Delete(fileName); 76 | File.WriteAllText(fileName, sb.ToString()); 77 | } 78 | 79 | //public string Build(int from, int to) 80 | //{ 81 | // StringBuilder sb = new StringBuilder((to - from) * 7); 82 | // for (int i = from; i < to; i++) 83 | // { 84 | // sb.Append(_times[i]); 85 | // sb.Append(";"); 86 | // for (int j = 0; j < _values.Count; j++) 87 | // { 88 | // sb.Append(_values[j][i] + ";"); 89 | // } 90 | // sb.Append("\n"); 91 | // } 92 | // return sb.ToString(); 93 | //} 94 | 95 | //public void SaveBinary(string fileName) 96 | //{ 97 | // byte[] bytes = new byte[_times.Count()]; 98 | // for (int i = 0; i < _times.Count(); i++) 99 | // { 100 | // bytes[i] = (byte)_values[i]; 101 | // } 102 | // File.WriteAllBytes(fileName, bytes); 103 | //} 104 | 105 | /* 106 | public void SaveOLS(string fileName, double samplingRate) 107 | { 108 | StringBuilder sb = new StringBuilder(_times.Length * 10); 109 | sb.AppendLine(";Rate: " + (int)samplingRate); 110 | sb.AppendLine(";Channels: 1"); 111 | for (int i = 0; i < _times.Count(); i++) 112 | { 113 | sb.AppendLine(((Int32)_values[i]).ToString("X") + "@" + i.ToString("X")); 114 | } 115 | File.Delete(fileName); 116 | File.WriteAllText(fileName, sb.ToString()); 117 | } 118 | */ 119 | 120 | /// 121 | /// Binarize Waveform Values given a threshold 122 | /// 123 | /// 124 | public WaveForm Threshold(double threshold) 125 | { 126 | // Apply threshold to all channels 127 | for (int channelIndex = 0; channelIndex < _values.Count; channelIndex++) 128 | { 129 | for (int index = 0; index < _values[channelIndex].Length; index++) 130 | { 131 | if (_values[channelIndex][index] >= threshold) 132 | { 133 | _values[channelIndex][index] = 1; 134 | } 135 | else 136 | { 137 | _values[channelIndex][index] = 0; 138 | } 139 | } 140 | } 141 | return this; 142 | } 143 | } -------------------------------------------------------------------------------- /OscilloscopeCLI/OscilloscopeCLI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {ECE2AD33-6CA7-43CA-9066-E9049D5D6FB0} 8 | Exe 9 | Properties 10 | OscilloscopeCLI 11 | OscilloscopeCLI 12 | v4.8 13 | 512 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {6bea399d-cd60-4af9-8499-3f720a5ede80} 53 | Oscilloscope 54 | 55 | 56 | 57 | 58 | 59 | 60 | 67 | -------------------------------------------------------------------------------- /OscilloscopeCLI/Program.cs: -------------------------------------------------------------------------------- 1 | // Author: Leonardo Tazzini 2 | 3 | using System; 4 | using System.Diagnostics; 5 | using System.Globalization; 6 | using System.Threading; 7 | 8 | namespace OscilloscopeCLI 9 | { 10 | class Program 11 | { 12 | static string csvFileName = "data.csv"; 13 | 14 | // Sample usage of Oscilloscope library 15 | static void Main(string[] args) 16 | { 17 | // Decimal separator is '.' 18 | Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); 19 | 20 | LongMemoryAcquisitionExample(); 21 | 22 | // Display acquired data 23 | Process.Start(csvFileName); 24 | 25 | // Draw CSV file with GNU Plot 26 | GnuPlot gnuPlot = new GnuPlot(); // NB: change path of gnuplot.exe with alternative constructor 27 | gnuPlot.DrawGraph(csvFileName, 1); 28 | 29 | // OscilloscopePromptExample(); 30 | } 31 | 32 | // 1M data point acquisition 33 | static void LongMemoryAcquisitionExample() 34 | { 35 | Oscilloscope rigol = new Oscilloscope(); 36 | rigol.Run(); 37 | rigol.SetWaveformPointsMode(PointsMode.Maximum); 38 | rigol.SetAcquireMemoryDepth(AcquireMemoryDepth.Long); 39 | rigol.SetTriggerSweep(TriggerSweep.Single); 40 | rigol.WaitTriggerStop(); 41 | rigol.Stop(); 42 | WaveForm wave = rigol.Channel1.GetWaveform(); 43 | wave.SaveCSV(csvFileName); 44 | rigol.Close(); 45 | } 46 | 47 | /// 48 | /// Simple Command Line Prompt for Rigol oscilloscope 49 | /// 50 | static void OscilloscopePromptExample() 51 | { 52 | Console.WriteLine("Oscilloscope Command Prompt"); 53 | Console.WriteLine("Instruments:"); 54 | string[] resources = Oscilloscope.GetResources(); 55 | for (int i = 0; i < resources.Length; i++) 56 | { 57 | Console.WriteLine("[" + i.ToString() + "]: " + resources[i]); 58 | } 59 | 60 | int resIndex; 61 | 62 | menu: 63 | if (!int.TryParse(Console.ReadLine().Trim(), out resIndex)) 64 | { 65 | Console.WriteLine("Please choose instrument "); 66 | goto menu; 67 | } 68 | 69 | Console.WriteLine("Example commands:"); 70 | Console.WriteLine("*IDN?"); 71 | Console.WriteLine(":WAVEFORM:DATA? CHAN1"); 72 | Console.WriteLine("quit"); 73 | 74 | // Create instance of Oscilloscope class and stop any acquisition 75 | Oscilloscope rigol = new Oscilloscope(resources[resIndex]); 76 | while (true) 77 | { 78 | Console.Write(">"); 79 | string cmd = Console.ReadLine(); 80 | if (cmd == "quit") 81 | break; 82 | rigol.Write(cmd); 83 | if (cmd.Contains("?")) 84 | { 85 | Console.WriteLine(rigol.ReadString()); 86 | } 87 | } 88 | rigol.Close(); 89 | } 90 | 91 | } 92 | } -------------------------------------------------------------------------------- /OscilloscopeCLI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("OscilloscopeCLI")] 9 | [assembly: AssemblyProduct("OscilloscopeCLI")] 10 | [assembly: AssemblyCopyright("Copyright © Leonardo Tazzini 2014")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("1091dc2a-4e99-4bca-9f0f-23d8c28f1312")] 19 | 20 | // Version information for an assembly consists of the following four values: 21 | // 22 | // Major Version 23 | // Minor Version 24 | // Build Number 25 | // Revision 26 | // 27 | // You can specify all the values or you can default the Build and Revision Numbers 28 | // by using the '*' as shown below: 29 | // [assembly: AssemblyVersion("1.0.*")] 30 | [assembly: AssemblyVersion("1.1.0.0")] 31 | [assembly: AssemblyFileVersion("1.1.0.0")] 32 | -------------------------------------------------------------------------------- /OscilloscopeCLI/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /OscilloscopeGUI/FrmMain.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace OscilloscopeGUI 2 | { 3 | partial class FrmMain 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmMain)); 32 | this.cbResources = new System.Windows.Forms.ComboBox(); 33 | this.btnConnect = new System.Windows.Forms.Button(); 34 | this.groupBox1 = new System.Windows.Forms.GroupBox(); 35 | this.lblPoints = new System.Windows.Forms.Label(); 36 | this.label5 = new System.Windows.Forms.Label(); 37 | this.panel1 = new System.Windows.Forms.Panel(); 38 | this.rbLong = new System.Windows.Forms.RadioButton(); 39 | this.rbNormal = new System.Windows.Forms.RadioButton(); 40 | this.rbMaxPoints = new System.Windows.Forms.RadioButton(); 41 | this.rbNormalPoints = new System.Windows.Forms.RadioButton(); 42 | this.label4 = new System.Windows.Forms.Label(); 43 | this.label2 = new System.Windows.Forms.Label(); 44 | this.label1 = new System.Windows.Forms.Label(); 45 | this.cbCh2 = new System.Windows.Forms.CheckBox(); 46 | this.cbCh1 = new System.Windows.Forms.CheckBox(); 47 | this.btnSaveCSV = new System.Windows.Forms.Button(); 48 | this.rbOutGnuPlot = new System.Windows.Forms.RadioButton(); 49 | this.rbOutPNG = new System.Windows.Forms.RadioButton(); 50 | this.label6 = new System.Windows.Forms.Label(); 51 | this.btnRefreshDevices = new System.Windows.Forms.Button(); 52 | this.label3 = new System.Windows.Forms.Label(); 53 | this.txtGnuPlotPath = new System.Windows.Forms.TextBox(); 54 | this.groupBox1.SuspendLayout(); 55 | this.panel1.SuspendLayout(); 56 | this.SuspendLayout(); 57 | // 58 | // cbResources 59 | // 60 | this.cbResources.FormattingEnabled = true; 61 | this.cbResources.Location = new System.Drawing.Point(18, 18); 62 | this.cbResources.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 63 | this.cbResources.Name = "cbResources"; 64 | this.cbResources.Size = new System.Drawing.Size(298, 28); 65 | this.cbResources.TabIndex = 99; 66 | // 67 | // btnConnect 68 | // 69 | this.btnConnect.Location = new System.Drawing.Point(18, 63); 70 | this.btnConnect.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 71 | this.btnConnect.Name = "btnConnect"; 72 | this.btnConnect.Size = new System.Drawing.Size(420, 35); 73 | this.btnConnect.TabIndex = 1; 74 | this.btnConnect.Text = "&Connect to selected device"; 75 | this.btnConnect.UseVisualStyleBackColor = true; 76 | this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click); 77 | // 78 | // groupBox1 79 | // 80 | this.groupBox1.Controls.Add(this.lblPoints); 81 | this.groupBox1.Controls.Add(this.label5); 82 | this.groupBox1.Controls.Add(this.panel1); 83 | this.groupBox1.Controls.Add(this.rbMaxPoints); 84 | this.groupBox1.Controls.Add(this.rbNormalPoints); 85 | this.groupBox1.Controls.Add(this.label4); 86 | this.groupBox1.Controls.Add(this.label2); 87 | this.groupBox1.Controls.Add(this.label1); 88 | this.groupBox1.Controls.Add(this.cbCh2); 89 | this.groupBox1.Controls.Add(this.cbCh1); 90 | this.groupBox1.Location = new System.Drawing.Point(18, 109); 91 | this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 92 | this.groupBox1.Name = "groupBox1"; 93 | this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); 94 | this.groupBox1.Size = new System.Drawing.Size(420, 209); 95 | this.groupBox1.TabIndex = 9; 96 | this.groupBox1.TabStop = false; 97 | this.groupBox1.Text = "Acquisition"; 98 | // 99 | // lblPoints 100 | // 101 | this.lblPoints.AutoSize = true; 102 | this.lblPoints.Location = new System.Drawing.Point(138, 171); 103 | this.lblPoints.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 104 | this.lblPoints.Name = "lblPoints"; 105 | this.lblPoints.Size = new System.Drawing.Size(36, 20); 106 | this.lblPoints.TabIndex = 23; 107 | this.lblPoints.Text = "600"; 108 | // 109 | // label5 110 | // 111 | this.label5.AutoSize = true; 112 | this.label5.Location = new System.Drawing.Point(75, 171); 113 | this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 114 | this.label5.Name = "label5"; 115 | this.label5.Size = new System.Drawing.Size(53, 20); 116 | this.label5.TabIndex = 22; 117 | this.label5.Text = "Points"; 118 | // 119 | // panel1 120 | // 121 | this.panel1.Controls.Add(this.rbLong); 122 | this.panel1.Controls.Add(this.rbNormal); 123 | this.panel1.Location = new System.Drawing.Point(142, 71); 124 | this.panel1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 125 | this.panel1.Name = "panel1"; 126 | this.panel1.Size = new System.Drawing.Size(232, 37); 127 | this.panel1.TabIndex = 21; 128 | // 129 | // rbLong 130 | // 131 | this.rbLong.AutoSize = true; 132 | this.rbLong.Location = new System.Drawing.Point(120, 2); 133 | this.rbLong.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 134 | this.rbLong.Name = "rbLong"; 135 | this.rbLong.Size = new System.Drawing.Size(63, 24); 136 | this.rbLong.TabIndex = 15; 137 | this.rbLong.Text = "Long"; 138 | this.rbLong.UseVisualStyleBackColor = true; 139 | this.rbLong.CheckedChanged += new System.EventHandler(this.UpdatePoints); 140 | // 141 | // rbNormal 142 | // 143 | this.rbNormal.AutoSize = true; 144 | this.rbNormal.Checked = true; 145 | this.rbNormal.Location = new System.Drawing.Point(0, 2); 146 | this.rbNormal.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 147 | this.rbNormal.Name = "rbNormal"; 148 | this.rbNormal.Size = new System.Drawing.Size(77, 24); 149 | this.rbNormal.TabIndex = 12; 150 | this.rbNormal.TabStop = true; 151 | this.rbNormal.Text = "Normal"; 152 | this.rbNormal.UseVisualStyleBackColor = true; 153 | this.rbNormal.CheckedChanged += new System.EventHandler(this.UpdatePoints); 154 | // 155 | // rbMaxPoints 156 | // 157 | this.rbMaxPoints.AutoSize = true; 158 | this.rbMaxPoints.Location = new System.Drawing.Point(262, 108); 159 | this.rbMaxPoints.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 160 | this.rbMaxPoints.Name = "rbMaxPoints"; 161 | this.rbMaxPoints.Size = new System.Drawing.Size(94, 24); 162 | this.rbMaxPoints.TabIndex = 20; 163 | this.rbMaxPoints.Text = "Maximum"; 164 | this.rbMaxPoints.UseVisualStyleBackColor = true; 165 | this.rbMaxPoints.CheckedChanged += new System.EventHandler(this.UpdatePoints); 166 | // 167 | // rbNormalPoints 168 | // 169 | this.rbNormalPoints.AutoSize = true; 170 | this.rbNormalPoints.Checked = true; 171 | this.rbNormalPoints.Location = new System.Drawing.Point(142, 108); 172 | this.rbNormalPoints.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 173 | this.rbNormalPoints.Name = "rbNormalPoints"; 174 | this.rbNormalPoints.Size = new System.Drawing.Size(77, 24); 175 | this.rbNormalPoints.TabIndex = 19; 176 | this.rbNormalPoints.TabStop = true; 177 | this.rbNormalPoints.Text = "Normal"; 178 | this.rbNormalPoints.UseVisualStyleBackColor = true; 179 | this.rbNormalPoints.CheckedChanged += new System.EventHandler(this.UpdatePoints); 180 | // 181 | // label4 182 | // 183 | this.label4.AutoSize = true; 184 | this.label4.Location = new System.Drawing.Point(30, 111); 185 | this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 186 | this.label4.Name = "label4"; 187 | this.label4.Size = new System.Drawing.Size(97, 20); 188 | this.label4.TabIndex = 18; 189 | this.label4.Text = "Points Mode"; 190 | // 191 | // label2 192 | // 193 | this.label2.AutoSize = true; 194 | this.label2.Location = new System.Drawing.Point(18, 75); 195 | this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 196 | this.label2.Name = "label2"; 197 | this.label2.Size = new System.Drawing.Size(110, 20); 198 | this.label2.TabIndex = 17; 199 | this.label2.Text = "Memory depth"; 200 | // 201 | // label1 202 | // 203 | this.label1.AutoSize = true; 204 | this.label1.Location = new System.Drawing.Point(52, 38); 205 | this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 206 | this.label1.Name = "label1"; 207 | this.label1.Size = new System.Drawing.Size(76, 20); 208 | this.label1.TabIndex = 16; 209 | this.label1.Text = "Channels"; 210 | // 211 | // cbCh2 212 | // 213 | this.cbCh2.AutoSize = true; 214 | this.cbCh2.Location = new System.Drawing.Point(262, 37); 215 | this.cbCh2.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 216 | this.cbCh2.Name = "cbCh2"; 217 | this.cbCh2.Size = new System.Drawing.Size(100, 24); 218 | this.cbCh2.TabIndex = 14; 219 | this.cbCh2.Text = "Channel 2"; 220 | this.cbCh2.UseVisualStyleBackColor = true; 221 | this.cbCh2.CheckedChanged += new System.EventHandler(this.UpdatePoints); 222 | // 223 | // cbCh1 224 | // 225 | this.cbCh1.AutoSize = true; 226 | this.cbCh1.Checked = true; 227 | this.cbCh1.CheckState = System.Windows.Forms.CheckState.Checked; 228 | this.cbCh1.Location = new System.Drawing.Point(142, 37); 229 | this.cbCh1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 230 | this.cbCh1.Name = "cbCh1"; 231 | this.cbCh1.Size = new System.Drawing.Size(100, 24); 232 | this.cbCh1.TabIndex = 13; 233 | this.cbCh1.Text = "Channel 1"; 234 | this.cbCh1.UseVisualStyleBackColor = true; 235 | this.cbCh1.CheckedChanged += new System.EventHandler(this.UpdatePoints); 236 | // 237 | // btnSaveCSV 238 | // 239 | this.btnSaveCSV.Location = new System.Drawing.Point(18, 422); 240 | this.btnSaveCSV.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 241 | this.btnSaveCSV.Name = "btnSaveCSV"; 242 | this.btnSaveCSV.Size = new System.Drawing.Size(420, 35); 243 | this.btnSaveCSV.TabIndex = 100; 244 | this.btnSaveCSV.Text = "&Save CSV and output"; 245 | this.btnSaveCSV.UseVisualStyleBackColor = true; 246 | this.btnSaveCSV.Click += new System.EventHandler(this.btnSaveCSV_Click); 247 | // 248 | // rbOutGnuPlot 249 | // 250 | this.rbOutGnuPlot.AutoSize = true; 251 | this.rbOutGnuPlot.Location = new System.Drawing.Point(160, 386); 252 | this.rbOutGnuPlot.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 253 | this.rbOutGnuPlot.Name = "rbOutGnuPlot"; 254 | this.rbOutGnuPlot.Size = new System.Drawing.Size(85, 24); 255 | this.rbOutGnuPlot.TabIndex = 101; 256 | this.rbOutGnuPlot.Text = "GnuPlot"; 257 | this.rbOutGnuPlot.UseVisualStyleBackColor = true; 258 | // 259 | // rbOutPNG 260 | // 261 | this.rbOutPNG.AutoSize = true; 262 | this.rbOutPNG.Checked = true; 263 | this.rbOutPNG.Location = new System.Drawing.Point(280, 386); 264 | this.rbOutPNG.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 265 | this.rbOutPNG.Name = "rbOutPNG"; 266 | this.rbOutPNG.Size = new System.Drawing.Size(110, 24); 267 | this.rbOutPNG.TabIndex = 102; 268 | this.rbOutPNG.TabStop = true; 269 | this.rbOutPNG.Text = "PNG Image"; 270 | this.rbOutPNG.UseVisualStyleBackColor = true; 271 | // 272 | // label6 273 | // 274 | this.label6.AutoSize = true; 275 | this.label6.Location = new System.Drawing.Point(88, 386); 276 | this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 277 | this.label6.Name = "label6"; 278 | this.label6.Size = new System.Drawing.Size(58, 20); 279 | this.label6.TabIndex = 103; 280 | this.label6.Text = "Output"; 281 | // 282 | // btnRefreshDevices 283 | // 284 | this.btnRefreshDevices.Location = new System.Drawing.Point(326, 14); 285 | this.btnRefreshDevices.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 286 | this.btnRefreshDevices.Name = "btnRefreshDevices"; 287 | this.btnRefreshDevices.Size = new System.Drawing.Size(112, 35); 288 | this.btnRefreshDevices.TabIndex = 104; 289 | this.btnRefreshDevices.Text = "&Refresh"; 290 | this.btnRefreshDevices.UseVisualStyleBackColor = true; 291 | this.btnRefreshDevices.Click += new System.EventHandler(this.btnRefreshDevices_Click); 292 | // 293 | // label3 294 | // 295 | this.label3.AutoSize = true; 296 | this.label3.Location = new System.Drawing.Point(18, 338); 297 | this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); 298 | this.label3.Name = "label3"; 299 | this.label3.Size = new System.Drawing.Size(104, 20); 300 | this.label3.TabIndex = 105; 301 | this.label3.Text = "GnuPlot Path"; 302 | // 303 | // txtGnuPlotPath 304 | // 305 | this.txtGnuPlotPath.Location = new System.Drawing.Point(135, 334); 306 | this.txtGnuPlotPath.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 307 | this.txtGnuPlotPath.Name = "txtGnuPlotPath"; 308 | this.txtGnuPlotPath.Size = new System.Drawing.Size(303, 26); 309 | this.txtGnuPlotPath.TabIndex = 106; 310 | // 311 | // FrmMain 312 | // 313 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); 314 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 315 | this.ClientSize = new System.Drawing.Size(458, 474); 316 | this.Controls.Add(this.txtGnuPlotPath); 317 | this.Controls.Add(this.label3); 318 | this.Controls.Add(this.btnRefreshDevices); 319 | this.Controls.Add(this.label6); 320 | this.Controls.Add(this.rbOutPNG); 321 | this.Controls.Add(this.rbOutGnuPlot); 322 | this.Controls.Add(this.btnSaveCSV); 323 | this.Controls.Add(this.groupBox1); 324 | this.Controls.Add(this.btnConnect); 325 | this.Controls.Add(this.cbResources); 326 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 327 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 328 | this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 329 | this.MaximizeBox = false; 330 | this.Name = "FrmMain"; 331 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 332 | this.Text = "Oscilloscope GUI v1.1"; 333 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmMain_FormClosing); 334 | this.Load += new System.EventHandler(this.FrmMain_Load); 335 | this.groupBox1.ResumeLayout(false); 336 | this.groupBox1.PerformLayout(); 337 | this.panel1.ResumeLayout(false); 338 | this.panel1.PerformLayout(); 339 | this.ResumeLayout(false); 340 | this.PerformLayout(); 341 | 342 | } 343 | 344 | #endregion 345 | 346 | private System.Windows.Forms.ComboBox cbResources; 347 | private System.Windows.Forms.Button btnConnect; 348 | private System.Windows.Forms.GroupBox groupBox1; 349 | private System.Windows.Forms.Label label2; 350 | private System.Windows.Forms.Label label1; 351 | private System.Windows.Forms.CheckBox cbCh2; 352 | private System.Windows.Forms.CheckBox cbCh1; 353 | private System.Windows.Forms.RadioButton rbMaxPoints; 354 | private System.Windows.Forms.RadioButton rbNormalPoints; 355 | private System.Windows.Forms.Label label4; 356 | private System.Windows.Forms.Panel panel1; 357 | private System.Windows.Forms.RadioButton rbLong; 358 | private System.Windows.Forms.RadioButton rbNormal; 359 | private System.Windows.Forms.Label label5; 360 | private System.Windows.Forms.Label lblPoints; 361 | private System.Windows.Forms.Button btnSaveCSV; 362 | private System.Windows.Forms.RadioButton rbOutGnuPlot; 363 | private System.Windows.Forms.RadioButton rbOutPNG; 364 | private System.Windows.Forms.Label label6; 365 | private System.Windows.Forms.Button btnRefreshDevices; 366 | private System.Windows.Forms.Label label3; 367 | private System.Windows.Forms.TextBox txtGnuPlotPath; 368 | } 369 | } 370 | 371 | -------------------------------------------------------------------------------- /OscilloscopeGUI/FrmMain.cs: -------------------------------------------------------------------------------- 1 | // Author: Leonardo Tazzini 2 | 3 | using System; 4 | using System.Windows.Forms; 5 | 6 | namespace OscilloscopeGUI 7 | { 8 | /// 9 | /// Sample GUI for acquiring Normal / Long memory mode and Normal / Maximum Points mode 10 | /// 11 | public partial class FrmMain : Form 12 | { 13 | Oscilloscope _osc; 14 | GnuPlot _gnuplot = new GnuPlot(); 15 | 16 | public FrmMain() 17 | { 18 | InitializeComponent(); 19 | } 20 | void FrmMain_Load(object sender, EventArgs e) 21 | { 22 | // Update GnuPlot path 23 | txtGnuPlotPath.Text = _gnuplot.Path; 24 | RefreshDevices(); 25 | // Are there connected devices? 26 | if (cbResources.Items.Count == 0) 27 | { 28 | MessageBox.Show("Please connect an oscilloscope, then click Refresh"); 29 | } 30 | } 31 | void btnConnect_Click(object sender, EventArgs e) 32 | { 33 | if (cbResources.Items.Count == 0) 34 | { 35 | MessageBox.Show("Please connect an oscilloscope, then click Refresh"); 36 | return; 37 | } 38 | if(string.IsNullOrWhiteSpace(cbResources.Text)) 39 | { 40 | MessageBox.Show("Please select a device"); 41 | return; 42 | } 43 | _osc = new Oscilloscope(cbResources.Text); 44 | 45 | } 46 | void btnSaveCSV_Click(object sender, EventArgs e) 47 | { 48 | SaveCSV(); 49 | } 50 | void btnRefreshDevices_Click(object sender, EventArgs e) 51 | { 52 | RefreshDevices(); 53 | } 54 | public void RefreshDevices() 55 | { 56 | cbResources.Items.Clear(); 57 | cbResources.Items.AddRange(Oscilloscope.GetResources()); 58 | cbResources.SelectedIndex = cbResources.Items.Count - 1; 59 | } 60 | public void SaveCSV() 61 | { 62 | if (_osc == null) 63 | { 64 | MessageBox.Show("Please connect a device first"); 65 | return; 66 | } 67 | 68 | Cursor = Cursors.WaitCursor; 69 | _gnuplot.Path = txtGnuPlotPath.Text; 70 | 71 | _osc.Run(); 72 | 73 | // Set up some settings on oscilloscope 74 | if (rbNormalPoints.Checked) 75 | { 76 | _osc.SetWaveformPointsMode(PointsMode.Normal); 77 | } 78 | else 79 | { 80 | _osc.SetWaveformPointsMode(PointsMode.Maximum); 81 | } 82 | 83 | // Memory depth 84 | if (rbNormal.Checked) 85 | { 86 | _osc.SetAcquireMemoryDepth(AcquireMemoryDepth.Normal); 87 | } 88 | else 89 | { 90 | _osc.SetAcquireMemoryDepth(AcquireMemoryDepth.Long); 91 | } 92 | 93 | _osc.SetTriggerSweep(TriggerSweep.Single); 94 | //_osc.Stop(); 95 | // Run and wait trigger 96 | _osc.Run(); 97 | _osc.WaitTriggerStop(); 98 | 99 | // Get Waveform and save it as CSV file 100 | string csvFileName = "data.csv"; 101 | 102 | if (cbCh1.Checked && cbCh2.Checked) 103 | { 104 | _osc.GetWaveforms().SaveCSV(csvFileName); 105 | _gnuplot.DrawGraph(csvFileName, 2, rbOutPNG.Checked); 106 | } 107 | else 108 | { 109 | if (cbCh1.Checked) 110 | { 111 | _osc.Channel1.GetWaveform().SaveCSV(csvFileName); 112 | // Draw CSV file with GNU Plot 113 | _gnuplot.DrawGraph(csvFileName, 1, rbOutPNG.Checked); 114 | } 115 | else if (cbCh2.Checked) 116 | { 117 | _osc.Channel2.GetWaveform().SaveCSV(csvFileName); 118 | _gnuplot.DrawGraph(csvFileName, 1, rbOutPNG.Checked); 119 | } 120 | else 121 | { 122 | // Nothing 123 | } 124 | } 125 | 126 | // Release oscilloscope remote control 127 | _osc.Close(); 128 | 129 | Cursor = Cursors.Default; 130 | } 131 | 132 | void UpdatePoints(object sender, EventArgs e) 133 | { 134 | int points = 0; 135 | if (!cbCh1.Checked && !cbCh2.Checked) 136 | { 137 | points = 0; 138 | } 139 | else 140 | { 141 | if (rbNormalPoints.Checked) 142 | { 143 | points = 600; 144 | } 145 | else // Max Points 146 | { 147 | if (rbNormal.Checked) 148 | { 149 | if (cbCh1.Checked && cbCh2.Checked) 150 | { 151 | points = 8192; 152 | } 153 | else 154 | { 155 | points = 16384; 156 | } 157 | } 158 | else 159 | { 160 | if (cbCh1.Checked && cbCh2.Checked) 161 | { 162 | points = 524288; 163 | } 164 | else 165 | { 166 | points = 1048576; 167 | } 168 | } 169 | } 170 | } 171 | lblPoints.Text = points.ToString(); 172 | } 173 | 174 | void FrmMain_FormClosing(object sender, FormClosingEventArgs e) 175 | { 176 | // SaveCSV already close device but here we close it again for double check 177 | _osc?.Close(); 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /OscilloscopeGUI/FrmMain.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | 123 | AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAEAAABMLAAATCwAAAAAAAAAA 124 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 125 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 126 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 127 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 128 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 129 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 130 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 131 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 132 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 133 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 134 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 135 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 136 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 137 | 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 165 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8bwcBvG8HBvxvBwb8bwcG/G8 166 | HBsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 167 | AAAAAAAAAAAAAAAAAAAAAAAA8b0fB/G9Hx/xvR8f8b0fH/G9Hx/yvh8IAAAAAAAAAAAAAAAAAAAAAAAA 168 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 169 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPG9 170 | HwnxvR8f8b0fH/G9Hx/xvR8fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 171 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPK+IQjyviEj8r4hI/K+ISPyviEj8r4hHfK/ 172 | IQvyvyIJ8r8iCfK/IgnyvyIJ8r8iCfK/IgnyvyIJ8r8iCfK/IgnyvyIJ8r8iCfK/IgnyvyIJ8r8iCfK/ 173 | IgnyvyIJ8r8iCfK/IgnyvyIJ8r8iCfK/IgnyvyIJ8r8iCfK/IgnyvyIJ8r8iCfK/IgnyvyIJ8r8iCfK/ 174 | IgnyvyIJ8r8iCfK/IQvyviEd8r4hI/K+ISPyviEj8r4hIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 175 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADywCME8sAjJ/LA 176 | IyfywCMn8sAjJ/LAIyfywCMn8sAjJ/LAIyfywCMn8sAjJ/LAIyfywCMn8sAjJ/LAIyfywCMn8sAjJ/LA 177 | IyfywCMn8sAjJ/LAIyfywCMn8sAjJ/LAIyfywCMn8sAjJ/LAIyfywCMn8sAjJ/LAIyfywCMn8sAjJ/LA 178 | IyfywCMn8sAjJ/LAIyfywCMn8sAjJ/LAIyfywCMn8sAjJ/LAIyfywCMn8sAjJ/LAIycAAAAAAAAAAAAA 179 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 180 | AAAAAAAAAAAAAPLBJSXywSUr8sElK/LBJSvywSUr8sElK/LBJSvywSUr8sElK/LBJSvywSUr8sElK/LB 181 | JSvywSUr8sElK/LBJSvywSUr8sElK/LBJSvywSUr8sElK/LBJSvywSUr8sElK/LBJSvywSUr8sElK/LB 182 | JSvywSUr8sElK/LBJSvywSUr8sElK/LBJSvywSUr8sElK/LBJSvywSUr8sElK/LBJSvywSUr8sElK/LB 183 | JSvywSUlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 184 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADzwicO88IoL/PCKC/zwigv88IoL/PCKC/zwigv88IoL/PC 185 | KC/zwigv88IoL/PCKC/zwigv88IoL/PCKC/zwigv88IoL/PCKC/zwigv88IoL/PCKC/zwigv88IoL/PC 186 | KC/zwigv88IoL/PCKC/zwigv88IoL/PCKC/zwigv88IoL/PCKC/zwigv88IoL/PCKC/zwigv88IoL/PC 187 | KC/zwigv88IoL/PCKC/zwigv88InDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 188 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPDKQ/zwyks88MqM/PD 189 | KjPzwyoz88MqM/PDKjPzwyoz88MqM/PDKjPzwyoz88MqM/PDKjPzwyoz88MqM/PDKjPzwyoz88MqM/PD 190 | KjPzwyoz88MqM/PDKjPzwyoz88MqM/PDKjPzwyoz88MqM/PDKjPzwyoz88MqM/PDKjPzwyoz88MqM/PD 191 | KjPzwyoz88MqM/PDKjPzwyoz88MqM/PDKjPzwyks88MpDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 192 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 193 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 194 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 195 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 196 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 197 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADalQAf2pUAP9qVAD/alQA/2pUAP9qVAD/alQA/2pUAP9qV 198 | AD/alQA/2pUAP9qVAD/alQA/2pUAP9qVAD/alQA/2pUAP9qVAD/alQA/2pUAP9qVAD/alQA/2pUAP9qV 199 | AD/alQA/2pUAP9qVAD/alQA/2pUAP9qVAD/alQA/2pUAP9qVAD/alQA/2pUAP9qVAD/alQA/2pUAHwAA 200 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 201 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANuWAE/alQDf2pUA/9qVAP/alQD/2pUA/9qV 202 | AP/alQD/2pUA/9qVAP/alQD/2pUA/9qVAP/alQD/2pUA/9qVAP/alQD/2pUA/9qVAP/alQD/2pUA/9qV 203 | AP/alQD/2pUA/9qVAP/alQD/2pUA/9qVAP/alQD/2pUA/9qVAP/alQD/2pUA/9qVAP/alQD/2pUA/9qV 204 | AP/alQD/2pUA/9qVAP/alQDf25YATwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 205 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANyXAE/blwD/25cA/9uX 206 | AP/blwD/25cA/9uXAP/blwD/25cA/9uXAP/blwD/25cA/9uXAP/blwD/25cA/9uXAP/blwD/25cA/9uX 207 | AP/blwD/25cA/9uXAP/blwD/25cA/9uXAP/blwD/25cA/9uXAP/blwD/25cA/9uXAP/blwD/25cA/9uX 208 | AP/blwD/25cA/9uXAP/blwD/25cA/9uXAP/blwD/25cA/9uXAP/clwBPAAAAAAAAAAAAAAAAAAAAAAAA 209 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 210 | AADcmADf3JgA/9yYAP/cmAD/3JgA/9yYAP/cmAD/3JgA/9yYAP/cmAD/3JgA/9yYAP/cmAD/3JgA/9yY 211 | AP/cmAD/3JgA/9yYAP/cmAD/3JgA/9yYAP/cmAD/3JgA/9yYAP/cmAD/3JgA/9yYAP/cmAD/3JgA/9yY 212 | AP/cmAD/3JgA/9yYAP/cmAD/3JgA/9yYAP/cmAD/3JgA/9yYAP/cmAD/3JgA/9yYAP/cmAD/3JgA3wAA 213 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 214 | AAAAAAAAAAAAAAAAAADemgAf3ZkA/92ZAP/dmQD/3ZkA/92ZAP/dmQD/3ZkA/92ZAP/dmQD/3ZkA/92Z 215 | AP/dmQD/3ZkA/92ZAP/dmQD/3ZkA/92ZAP/dmQD/3ZkA/92ZAP/dmQD/3ZkA/92ZAP/dmQD/3ZkA/92Z 216 | AP/dmQD/3ZkA/92ZAP/dmQD/3ZkA/92ZAP/dmQD/3ZkA/92ZAP/dmQD/3ZkA/92ZAP/dmQD/3ZkA/92Z 217 | AP/dmQD/3ZkA/92ZAP/emgAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 218 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3psAP96bAP/emwD/3psA/96bAP/emwDP3psATwAA 219 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 220 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 221 | 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 249 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 250 | AAAAAAAAAAAAAAAAAAAAAAAA4p8Ar+KfAP/inwD/4p8A3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 251 | AAAAAAAA5qQA/+akAP/mpAD/5qQA/+akAD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 252 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADnpQA/56UA/+elAP/npQD/56UA/wAA 253 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 254 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOOhAL/joQD/46EA/+OhAP/kogAPAAAAAAAA 255 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAOelAP/npQD/56UA/+elAP/npQA/AAAAAAAAAAAAAAAAAAAAAAAA 256 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6KYAP+im 257 | AP/opgD/6KYA/+imAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 258 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlowD/5aMA/+Wj 259 | AP/lowD/5aMAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADopgD/6KYA/+imAP/opgD/6KYAPwAA 260 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 261 | AAAAAAAAAAAAAOmoAD/pqAD/6agA/+moAP/pqAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 262 | AAAAAAAAAAAAAAAAAAAAAAAA6KYAD+elAO/npQDv6KYADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 263 | AADopgAP56UA/+elAP/npQD/56UA/+elAH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6agA/+mo 264 | AP/pqAD/6agA/+moAD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 265 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADqqQA/6qkA/+qpAP/qqQD/6qkA/wAAAAAAAAAAAAAAAAAA 266 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOmoAE/ppwD/6acA/+moAH8AAAAAAAAAAAAA 267 | AAAAAAAAAAAAAAAAAAAAAAAA6acAP+mnAP/ppwD/6KcAv+mnAP/ppwCvAAAAAAAAAAAAAAAAAAAAAAAA 268 | AAAAAAAAAAAAAOqpAP/qqQD/6qkA/+qpAP/qqQA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 269 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA66oAP+uqAP/rqgD/66oA/+uq 270 | AP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADqqgCf6qoA/+qq 271 | AP/qqgDv66sADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOqqAF/qqgD/6qoA/+qqAH/qqgD/6qoA3+ur 272 | AD/rqwA/66sAP+urAD/rqwA/AAAAAAAAAADrqgD/66oA/+uqAP/rqgD/66oAPwAAAAAAAAAAAAAAAAAA 273 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOys 274 | AD/srAD/7KwA/+ysAP/srAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 275 | AAAAAAAA7KwA3+ysAP/srAD/7KwA/+ysAH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADsrAB/7KwA/+ys 276 | AL/srAA/7KwA/+ysAP/srAD/7KwA/+ysAP/srAD/7KwA/+ysAO8AAAAA7KwA/+ysAP/srAD/7KwA/+ys 277 | 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 333 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8bwcP/G8HP/xvBz/8bwc//G8 334 | HP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 335 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 336 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPG9HQ/xvBz/8bwc//G8HP/xvBz/8bwcPwAAAAAAAAAAAAAAAAAA 337 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPG9 338 | Hz/xvR//8b0f//G9H//xvR//8b0fTwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 339 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 340 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxvR9P8b0f//G9H//xvR//8b0f//G9 341 | Hz8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 342 | AAAAAAAAAAAAAAAAAADyviE/8r4h//K+If/yviH/8r4h//K+Ic/yvyFP8r8iP/K/Ij/yvyI/8r8iP/K/ 343 | Ij/yvyI/8r8iP/K/Ij/yvyI/8r8iP/K/Ij/yvyI/8r8iP/K/Ij/yvyI/8r8iP/K/Ij/yvyI/8r8iP/K/ 344 | Ij/yvyI/8r8iP/K/Ij/yvyI/8r8iP/K/Ij/yvyI/8r8iP/K/Ij/yvyI/8r8iP/K/Ij/yvyFP8r4hz/K+ 345 | If/yviH/8r4h//K+If/yviE/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 346 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8sAiH/LAI//ywCP/8sAj//LAI//ywCP/8sAj//LA 347 | I//ywCP/8sAj//LAI//ywCP/8sAj//LAI//ywCP/8sAj//LAI//ywCP/8sAj//LAI//ywCP/8sAj//LA 348 | I//ywCP/8sAj//LAI//ywCP/8sAj//LAI//ywCP/8sAj//LAI//ywCP/8sAj//LAI//ywCP/8sAj//LA 349 | I//ywCP/8sAj//LAI//ywCP/8sAj//LAI//ywCP/8sAiHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 350 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADywSXf8sEl//LB 351 | Jf/ywSX/8sEl//LBJf/ywSX/8sEl//LBJf/ywSX/8sEl//LBJf/ywSX/8sEl//LBJf/ywSX/8sEl//LB 352 | Jf/ywSX/8sEl//LBJf/ywSX/8sEl//LBJf/ywSX/8sEl//LBJf/ywSX/8sEl//LBJf/ywSX/8sEl//LB 353 | Jf/ywSX/8sEl//LBJf/ywSX/8sEl//LBJf/ywSX/8sEl//LBJf/ywSX/8sEl3wAAAAAAAAAAAAAAAAAA 354 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 355 | AAAAAAAA88InT/PCKP/zwij/88Io//PCKP/zwij/88Io//PCKP/zwij/88Io//PCKP/zwij/88Io//PC 356 | KP/zwij/88Io//PCKP/zwij/88Io//PCKP/zwij/88Io//PCKP/zwij/88Io//PCKP/zwij/88Io//PC 357 | KP/zwij/88Io//PCKP/zwij/88Io//PCKP/zwij/88Io//PCKP/zwij/88Io//PCKP/zwij/88Io//PC 358 | J08AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 359 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADzwylP88Mp3/PDKv/zwyr/88Mq//PDKv/zwyr/88Mq//PD 360 | Kv/zwyr/88Mq//PDKv/zwyr/88Mq//PDKv/zwyr/88Mq//PDKv/zwyr/88Mq//PDKv/zwyr/88Mq//PD 361 | Kv/zwyr/88Mq//PDKv/zwyr/88Mq//PDKv/zwyr/88Mq//PDKv/zwyr/88Mq//PDKv/zwyr/88Mq//PD 362 | Kv/zwyr/88Mp3/PDKU8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 363 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADzxCsf88QrP/PE 364 | Kz/zxCs/88QrP/PEKz/zxCs/88QrP/PEKz/zxCs/88QrP/PEKz/zxCs/88QrP/PEKz/zxCs/88QrP/PE 365 | Kz/zxCs/88QrP/PEKz/zxCs/88QrP/PEKz/zxCs/88QrP/PEKz/zxCs/88QrP/PEKz/zxCs/88QrP/PE 366 | Kz/zxCs/88QrP/PEKz/zxCs/88QrHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 367 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 368 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 369 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 370 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 371 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 372 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 373 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 374 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 375 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 376 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 377 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 378 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 379 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 380 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 381 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 382 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 383 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 384 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 385 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 386 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 387 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 388 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 389 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 390 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 391 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 392 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 393 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 394 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 395 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 396 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 397 | AAAAAAAA/////////////////////////////////8P///w/w///g////D+D//+D///8P4P//4P///w/ 398 | g///g////D+D//+D///8P4P//4P/////g///gf////+D//+AAAAAAAP//4AAAAAAA///wAAAAAAD///A 399 | AAAAAAP//+AAAAAAB//////////////4AAAAAB///+AAAAAAB///wAAAAAAD///AAAAAAAP//4AAAAAA 400 | Af//gP////4B//+B/////4H//4P/////wf//g////D/B//+D///8P8H//4P///w/wf//g////D/B//+D 401 | ///8P8H//4P///wfwf//g////B/B//+D/8P4H8H//4P/w/gfwf//g//B+ADB//+D/8H4AEH//4IAgPgA 402 | Qf//ggCA+P/B//+D+IgY/8H//4P4CAD/wf//g/wMAP/B//+D/B+B/8H//4P+H4H/wf//g/4fwf/B//+D 403 | /h/B/8H//4P//+H/wf//g///4f/B//+D///h/8H//4P/////wf//g/////+B//+B/////4H//4AAAAAA 404 | Af//gAAAAAAB///AAAAAAAP//8AAAAAAA///4AAAAAAH///4AAAAAB////////////////////////// 405 | //////////////////////////////////////////////////8= 406 | 407 | 408 | -------------------------------------------------------------------------------- /OscilloscopeGUI/OscilloscopeGUI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {ADFC469D-78BB-415D-AE23-B6F5D5A5BDFC} 8 | WinExe 9 | Properties 10 | OscilloscopeGUI 11 | OscilloscopeGUI 12 | v4.8 13 | 512 14 | 15 | false 16 | publish\ 17 | true 18 | Disk 19 | false 20 | Foreground 21 | 7 22 | Days 23 | false 24 | false 25 | true 26 | 1 27 | 1.0.0.%2a 28 | false 29 | true 30 | true 31 | 32 | 33 | AnyCPU 34 | true 35 | full 36 | false 37 | bin\Debug\ 38 | DEBUG;TRACE 39 | prompt 40 | 4 41 | false 42 | Auto 43 | 44 | 45 | AnyCPU 46 | pdbonly 47 | true 48 | bin\Release\ 49 | TRACE 50 | prompt 51 | 4 52 | false 53 | false 54 | 55 | 56 | 5D4142EB70B461762E16F05A5C0356043FBFBF57 57 | 58 | 59 | OscilloscopeGUI_TemporaryKey.pfx 60 | 61 | 62 | false 63 | 64 | 65 | LocalIntranet 66 | 67 | 68 | Properties\app.manifest 69 | 70 | 71 | false 72 | 73 | 74 | oscilloscope.ico 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | Form 91 | 92 | 93 | FrmMain.cs 94 | 95 | 96 | 97 | 98 | FrmMain.cs 99 | 100 | 101 | Designer 102 | 103 | 104 | 105 | 106 | 107 | {6bea399d-cd60-4af9-8499-3f720a5ede80} 108 | Oscilloscope 109 | 110 | 111 | 112 | 113 | False 114 | Microsoft .NET Framework 4 %28x86 and x64%29 115 | true 116 | 117 | 118 | False 119 | .NET Framework 3.5 SP1 Client Profile 120 | false 121 | 122 | 123 | False 124 | .NET Framework 3.5 SP1 125 | false 126 | 127 | 128 | False 129 | Windows Installer 4.5 130 | true 131 | 132 | 133 | 134 | 135 | False 136 | 137 | 138 | 139 | 140 | Include 141 | True 142 | Assembly 143 | 144 | 145 | False 146 | 147 | 148 | 149 | 150 | Include 151 | True 152 | Assembly 153 | 154 | 155 | False 156 | 157 | 158 | 159 | 160 | Include 161 | True 162 | Assembly 163 | 164 | 165 | False 166 | 167 | 168 | 169 | 170 | Include 171 | True 172 | Assembly 173 | 174 | 175 | 176 | 177 | 178 | 179 | 186 | -------------------------------------------------------------------------------- /OscilloscopeGUI/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Threading; 4 | using System.Windows.Forms; 5 | 6 | namespace OscilloscopeGUI 7 | { 8 | static class Program 9 | { 10 | /// 11 | /// The main entry point for the application. 12 | /// 13 | [STAThread] 14 | static void Main() 15 | { 16 | // Decimal separator is '.' 17 | Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); 18 | 19 | Application.EnableVisualStyles(); 20 | Application.SetCompatibleTextRenderingDefault(false); 21 | Application.Run(new FrmMain()); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /OscilloscopeGUI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Oscilloscope GUI")] 9 | [assembly: AssemblyProduct("Oscilloscope GUI")] 10 | [assembly: AssemblyCopyright("Copyright © Leonardo Tazzini 2014")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("1587975a-0749-4064-90ed-a2f23e105380")] 19 | 20 | // Version information for an assembly consists of the following four values: 21 | // 22 | // Major Version 23 | // Minor Version 24 | // Build Number 25 | // Revision 26 | // 27 | // You can specify all the values or you can default the Build and Revision Numbers 28 | // by using the '*' as shown below: 29 | // [assembly: AssemblyVersion("1.0.*")] 30 | [assembly: AssemblyVersion("1.1.0.0")] 31 | [assembly: AssemblyFileVersion("1.1.0.0")] -------------------------------------------------------------------------------- /OscilloscopeGUI/Properties/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 54 | -------------------------------------------------------------------------------- /OscilloscopeGUI/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /OscilloscopeGUI/oscilloscope.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/electro-logic/Oscilloscope/0e2c02bed0aebfc0c84ac1a4b7d9095409adec9f/OscilloscopeGUI/oscilloscope.ico -------------------------------------------------------------------------------- /OscilloscopeTest/OscilloscopeTest.cs: -------------------------------------------------------------------------------- 1 | // Author: Leonardo Tazzini 2 | 3 | using System; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using System.Globalization; 6 | using System.Threading; 7 | 8 | namespace OscilloscopeTest 9 | { 10 | [TestClass] 11 | public class UnitTestOscilloscope 12 | { 13 | Oscilloscope _osc = new Oscilloscope(); 14 | 15 | [TestCleanup] 16 | [TestInitialize] 17 | [TestMethod] 18 | public void Initialize() 19 | { 20 | Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); 21 | _osc.SetAcquireAverages(AcquireAverages.Average16); 22 | _osc.SetAcquireMemoryDepth(AcquireMemoryDepth.Normal); 23 | _osc.SetAcquireMode(AcquireMode.EquiTime); 24 | _osc.SetAcquireType(AcquireType.Normal); 25 | _osc.SetTimebaseFormat(TimebaseFormat.YT); 26 | _osc.SetTimebaseMode(TimebaseMode.Main); 27 | _osc.SetTriggerSweep(TriggerSweep.Normal); 28 | _osc.SetWaveformPointsMode(PointsMode.Normal); 29 | _osc.SetTimebaseScale(0.001); 30 | _osc.SetTimebaseOffset(0); 31 | } 32 | 33 | /// 34 | /// TODO: Document 35 | /// 36 | public void TestGetterSetter(Func getter, Action setter) 37 | { 38 | Array enums = Enum.GetValues(typeof(T)); 39 | foreach (T enumObj in enums) 40 | { 41 | setter(enumObj); 42 | Assert.AreEqual(enumObj, getter()); 43 | } 44 | 45 | // Test first Setter in case of already set enum 46 | T firstEnumObj = (T)enums.GetValue(0); 47 | setter(firstEnumObj); 48 | Assert.AreEqual(firstEnumObj, getter()); 49 | } 50 | 51 | [TestMethod] 52 | public void TestAcquire() 53 | { 54 | TestGetterSetter(_osc.GetAcquireType, _osc.SetAcquireType); 55 | TestGetterSetter(_osc.GetAcquireMode, _osc.SetAcquireMode); 56 | TestGetterSetter(_osc.GetAcquireAverages, _osc.SetAcquireAverages); 57 | TestGetterSetter(_osc.GetAcquireMemoryDepth, _osc.SetAcquireMemoryDepth); 58 | } 59 | 60 | //[TestMethod] 61 | //public void TestAcquireSamplingRate() 62 | //{ 63 | // // TODO: Set sampling rate changing timebase scale 64 | // double samplingRate = _osc.GetAcquireSamplingRate(1); 65 | // Assert.AreEqual(1.0, samplingRate); 66 | //} 67 | 68 | [TestMethod] 69 | public void TestTimebase() 70 | { 71 | //TestGetterSetter(_osc.GetTimebaseMode, _osc.SetTimebaseMode); 72 | // TODO 73 | // _osc.GetTimebaseOffset 74 | // _osc.GetTimebaseScale 75 | TestGetterSetter(_osc.GetTimebaseFormat, _osc.SetTimebaseFormat); 76 | } 77 | 78 | [TestMethod] 79 | public void TestTrigger() 80 | { 81 | TestGetterSetter(_osc.GetTriggerSweep, _osc.SetTriggerSweep); 82 | // TODO others 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /OscilloscopeTest/OscilloscopeTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {38B8E55F-06FF-435F-8D4A-0967A9B94F4F} 7 | Library 8 | Properties 9 | OscilloscopeTest 10 | OscilloscopeTest 11 | v4.8 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | 20 | 21 | 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | false 30 | 31 | 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE 36 | prompt 37 | 4 38 | false 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | {6bea399d-cd60-4af9-8499-3f720a5ede80} 62 | Oscilloscope 63 | 64 | 65 | 66 | 67 | 68 | 69 | False 70 | 71 | 72 | False 73 | 74 | 75 | False 76 | 77 | 78 | False 79 | 80 | 81 | 82 | 83 | 84 | 85 | 92 | -------------------------------------------------------------------------------- /OscilloscopeTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("OscilloscopeTest")] 9 | [assembly: AssemblyProduct("OscilloscopeTest")] 10 | [assembly: AssemblyCopyright("Copyright © Leonardo Tazzini 2014")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("eb70b576-f8c1-4023-8e6a-256c455d3ce8")] 19 | 20 | // Version information for an assembly consists of the following four values: 21 | // 22 | // Major Version 23 | // Minor Version 24 | // Build Number 25 | // Revision 26 | // 27 | // You can specify all the values or you can default the Build and Revision Numbers 28 | // by using the '*' as shown below: 29 | // [assembly: AssemblyVersion("1.0.*")] 30 | [assembly: AssemblyVersion("1.1.0.0")] 31 | [assembly: AssemblyFileVersion("1.1.0.0")] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C# Oscilloscope Library and GUI (tested with Rigol DS1102E) 2 | 3 | Remote control your oscilloscope, configure settings and acquire data points 4 | 5 | 6 | ## Projects 7 | 8 | - OscilloscopeLib is an object-oriented library for managing Rigol's Oscilloscopes (tested with DS1102E only, but should works with other models too) 9 | 10 | - OscilloscopeCLI is a command line sample, showing how to use OscilloscopeLib 11 | 12 | - OscilloscopeGUI is a GUI for easy data acquisition and display 13 | 14 | - OscilloscopeTest contains Unit Tests for easily checking if your own oscilloscope model is compliant with library 15 | 16 | 17 | ## Requirements 18 | 19 | To compile the project you need: 20 | 21 | - .NET Framework 4.8 22 | 23 | - Visual Studio 2022 with .NET desktop development workload installed 24 | 25 | - NI-VISA .NET SDK 2024 Q4 [http://www.ni.com/download/ni-visa-run-time-engine](https://www.ni.com/en/support/downloads/drivers/download.ni-visa.html) 26 | 27 | To run the project you need: 28 | 29 | - NI-VISA .NET Runtime 2024 Q4 [http://www.ni.com/download/ni-visa-run-time-engine](https://www.ni.com/en/support/downloads/drivers/download.ni-visa.html) 30 | 31 | - Gnuplot 5.2 (optional for graphs, 25 MB) http://www.gnuplot.info/ see GNUPLOT section for more informations 32 | 33 | 34 | ## Screenshoots 35 | 36 | ![alt text](https://raw.githubusercontent.com/electro-logic/Oscilloscope/master/Docs/gui.png) 37 | 38 | *OscilloscopeGUI* 39 | 40 | ![alt text](https://raw.githubusercontent.com/electro-logic/Oscilloscope/master/Docs/gnuplot.png) 41 | 42 | *Automatically generated Gnuplot graph (zoomable)* 43 | 44 | 45 | ## Example of OscilloscopeLib usage (from OscilloscopeCLI) 46 | 47 | ``` 48 | // 1M data point acquisition 49 | void LongMemoryAcquisitionExample() 50 | { 51 | var rigol = new Oscilloscope(); 52 | rigol.Run(); 53 | rigol.SetWaveformPointsMode(PointsMode.Maximum); 54 | rigol.SetAcquireMemoryDepth(AcquireMemoryDepth.Long); 55 | rigol.SetTriggerSweep(TriggerSweep.Single); 56 | rigol.WaitTriggerStop(); 57 | rigol.Stop(); 58 | var wave = rigol.Channel1.GetWaveform(); 59 | wave.SaveCSV(csvFileName); 60 | rigol.Close(); 61 | } 62 | ``` 63 | 64 | Then you can graph your acquired data with Excel or GnuPlot 65 | 66 | ``` 67 | // Display acquired data with Excel (or any other installed software that can handle CSV) 68 | Process.Start(csvFileName); 69 | 70 | // Draw a graph with GNU Plot and save it as .png image 71 | GnuPlot gnuPlot = new GnuPlot(); 72 | gnuPlot.DrawGraph(csvFileName, 1); // only channel 1 73 | ``` 74 | 75 | 76 | ## Notes 77 | 78 | This project started as auxiliary tool for a bigger project, so code may not be production-quality. If there is interest I can improve it, anyway any contribution is welcome. 79 | 80 | I initially wrote this library in 2014 to track the velocity profile of a stepper motor, driven by a real-time driver that I have built. 81 | 82 | I think that this project can be useful to people who own a Rigol oscilloscope, so I updated it with NI-VISA 2024 Q4 to support Windows 11. 83 | 84 | 85 | Here are some images to better understand what this library allow you to do with very little work. 86 | 87 | 88 | ![alt text](https://raw.githubusercontent.com/electro-logic/Oscilloscope/master/Docs/oscilloscope.png) 89 | 90 | *Oscilloscope display* 91 | 92 | 93 | ![alt text](https://raw.githubusercontent.com/electro-logic/Oscilloscope/master/Docs/speed_graph.png) 94 | 95 | *Data acquired and processed with the aid of this library and a graph of velocity of the system produced* 96 | 97 | 98 | You can also write some C# code to post-process CSV data and extrapolate relevant information for your application (ex. I used it to get velocity profile of my system from the waveform of a revolution detector). 99 | 100 | 101 | ## VISA SDK 102 | 103 | Rigol oscilloscope support Virtual Instrument Software Architecture (VISA) standard for configuring, programming, and troubleshooting instrumentation systems. 104 | 105 | To create software that support VISA devices you need to install the NI-VISA SDK: 106 | 107 | 108 | Assembly referenced by OscilloscopeLib are located into: 109 | 110 | - C:\Program Files (x86)\IVI Foundation\VISA\Microsoft.NET\Framework32\v2.0.50727\VISA.NET Shared Components 7.2.0\Ivi.Visa.dll v7.2.0.0 111 | 112 | - C:\Program Files (x86)\IVI Foundation\VISA\Microsoft.NET\Framework32\v4.0.30319\NI VISA.NET 23.3\NationalInstruments.Visa.dll v23.3.0.49276 113 | 114 | 115 | Documentation and Programming Guide: 116 | 117 | [Rigol Prograrmming Guide](https://eu.rigol.com/eu/Images/DS1000E_ProgrammingGuide_EN_tcm30-2863.pdf) 118 | 119 | [DS1000E Waveform Data Formatting Guide](https://rigol.my.site.com/support/s/article/DS1000E-Waveform-Data-Formatting-Guide) 120 | 121 | 122 | ## GNUPLOT 123 | 124 | Graphs are generated with Gnuplot to avoid reinventing the wheel. Data can be analyzed and graphed also with Excel or any software that can open CSV files. 125 | 126 | Gnuplot 5.2 (for graphs, optional) 127 | 128 | http://www.gnuplot.info/ 129 | 130 | **NB:** Gnuplot keyboard commands to interact with graph are available at Gnuplot command line (just launch gnuplot.exe from Start) with the command "show bind", here are reported some: 131 | 132 | - a autoscale 133 | - \+ zoom in 134 | - \- zoom out 135 | 136 | Right click with the mouse to zoom a section of the graph 137 | 138 | *Warning:* Graph with 1M points can be slow to display and interact, another way can be analyzing data with Excel or another software 139 | 140 | 141 | ## ADDITIONAL NOTES 142 | 143 | For legacy systems (Windows XP, etc..) an old NI-VISA 3.0 Runtime download (3 MBytes) is distributed by Rigol with the UltraSigma software and can avoid downloading the most recent package that is much larger. NI-VISA 5.4.1 Runtime download (74 MBytes) is available for OS up to Windows 8. To avoid the NI-VISA Runtime (few Gigabytes), please have a look at the branch https://github.com/electro-logic/Oscilloscope/tree/TinyDriver that needs a tiny driver (24 KBytes) only. 144 | 145 | DS1102E firmware v00.04.04.00.00 (AUG 2020) is breaking the "Long Memory", it's advised to NOT update the firmware. Please also see https://www.eevblog.com/forum/testgear/rigol-ds1052e-firmware-v00-04-04-00-00-from-20200827 146 | 147 | 148 | ## OSZI WAVEFORM ANALYZER 149 | 150 | Another interesting project to capture and analyze data from Rigol oscilloscopes: https://github.com/Elmue/Oszi-Waveform-Analyzer 151 | --------------------------------------------------------------------------------