diff --git a/DataSources/DataPackages/DataPackageScope.cs b/DataSources/DataPackages/DataPackageScope.cs
index 201dec6..2b9b597 100644
--- a/DataSources/DataPackages/DataPackageScope.cs
+++ b/DataSources/DataPackages/DataPackageScope.cs
@@ -13,7 +13,9 @@ public enum DataSourceType
Viewport,
Overview
}
-
+ ///
+ /// Class representing an oscilloscope acquisition's channel data
+ ///
public class ChannelData
{
public DataSourceType source { get; private set; }
@@ -23,8 +25,22 @@ public class ChannelData
/// create a new array and with that, a new ChannelData object
///
public Array array { get; private set; }
+ ///
+ /// Gets a value indicating whether this is partial, i.e.
+ /// if more data is required to consider the acquisition complete. This can be false when the acquisition is still ongoing
+ /// while the data dump has already begun.
+ ///
+ /// true if partial; otherwise, false.
public bool partial { get; private set; }
+ ///
+ /// Time between 2 samples in seconds
+ ///
+ /// The sample period.
public double samplePeriod { get; private set; }
+ ///
+ /// Time offset of the first sample.
+ ///
+ /// The time offset.
public double timeOffset { get; private set; }
public ChannelData(DataSourceType t, Channel channel, Array data, bool partial, double samplePeriod, double timeOffset = 0)
{
diff --git a/Devices/DeviceManager.cs b/Devices/DeviceManager.cs
index 07d3a23..2149058 100644
--- a/Devices/DeviceManager.cs
+++ b/Devices/DeviceManager.cs
@@ -15,6 +15,10 @@ public class DeviceManager
{
DeviceConnectHandler connectHandler;
IDevice device;
+ ///
+ /// Gets the fallback device.
+ ///
+ /// The fallback device when no device is detected
public IDevice fallbackDevice { get; private set; }
Thread pollThread;
#if WINDOWS
@@ -84,6 +88,9 @@ private void PollUponStart()
public void Stop()
{
+ if (device is IScope)
+ ((IScope)device).DataSourceScope.Stop ();
+
if(pollThread != null)
pollThread.Join(100);
#if ANDROID
diff --git a/Devices/DummyScope.cs b/Devices/DummyScope.cs
index 65718a5..5952dbb 100644
--- a/Devices/DummyScope.cs
+++ b/Devices/DummyScope.cs
@@ -189,6 +189,9 @@ public AcquisitionMode AcquisitionMode
this.acquisitionMode = value;
}
}
+ get {
+ return this.acquisitionMode;
+ }
}
public bool Running {
@@ -243,6 +246,10 @@ public AnalogTriggerValue TriggerAnalog
public void SetVerticalRange(AnalogChannel ch, float minimum, float maximum)
{
}
+ public float[] GetVerticalRange(AnalogChannel ch)
+ {
+ return new float[] { -100f, 100f };
+ }
public void SetProbeDivision(AnalogChannel ch, ProbeDivision division)
{
ChannelConfig[ch].probeDivision = division;
diff --git a/Devices/IScope.cs b/Devices/IScope.cs
index ed955ba..f12f3e9 100644
--- a/Devices/IScope.cs
+++ b/Devices/IScope.cs
@@ -36,6 +36,14 @@ public enum TriggerModes { Analog, Digital, External };
public enum TriggerDirection { RISING = 0, FALLING = 1 };
public enum Coupling { AC, DC };
public enum AcquisitionMode { SINGLE = 2, NORMAL = 1, AUTO = 0};
+ ///
+ /// Digital trigger value.
+ /// L Low
+ /// H High
+ /// R Rising edge
+ /// F Falling edge
+ /// X Don't care
+ ///
public enum DigitalTriggerValue { L, H, R, F, X };
///
/// Describes an analog trigger
@@ -63,55 +71,214 @@ public AnalogTriggerValue Copy()
public interface IScope : IDevice
{
+ ///
+ /// Method to synchronously fetch scope data
+ ///
+ /// The scope data.
DataPackageScope GetScopeData();
+ ///
+ /// The DataSourceScope allows you to register a callback which
+ /// is called whenever new data comes in.
+ ///
+ /// Mind that the DataSourceScope must be started in order for the
+ /// fetch thread to run.
+ ///
+ /// The data source scope.
DataSources.DataSource DataSourceScope { get; }
+ ///
+ /// Enabel or disable rolling mode using this property
+ ///
bool Rolling { get; set; }
+ ///
+ /// Start or stop the scope using this property
+ ///
bool Running { get; set; }
+ ///
+ /// True when the scope can go into rolling mode
+ ///
bool CanRoll { get; }
+ ///
+ /// True when the acquistion will be stopped after the current one
+ ///
bool StopPending { get; }
+ ///
+ /// True when the scope is awaiting a trigger condition to occur.
+ ///
bool AwaitingTrigger { get; }
+ ///
+ /// True when the scope is armed and waiting for a trigger
+ ///
bool Armed { get; }
void Pause();
void Resume();
/* Acquisition & Trigger */
+
+ ///
+ /// When the sample rate is sufficiently low and data comes in slower than
+ /// the transfer rate of the scope to host, the scope can optionally stream
+ /// data yet available before the entire acqusition buffer is filled.
+ ///
+ /// When false, the scope will wait for the acquisition to complete before
+ /// streaming data to host. This ensures that only a single and viewport-complete
+ /// data package will reach the host per acquisition. If viewport settings are changed
+ /// while the current acquisition is not completed yet though, the scope can still
+ /// send data of that ongoing acquisition.
+ ///
+ /// In this mode, use the to
+ /// distinguish between different acquisitions.
+ ///
bool PreferPartial { get; set; }
- AcquisitionMode AcquisitionMode { set; }
+ ///
+ /// Sets the acquisition mode which defines the trigger behavoir
+ /// AUTO results in a timeout when no trigger is detected within 5ms
+ /// NORMAL a trigger is required for the acquisition to complete
+ /// SINGLE once a trigger is detected, the running acquisition will finalise
+ /// and the scope will stop after that.
+ ///
+ /// The acquisition mode.
+ AcquisitionMode AcquisitionMode { get; set; }
+ ///
+ /// Gets or sets the length of the acquisition buffer (in seconds)
+ ///
+ /// The length of the acquisition buffer (in seconds)
double AcquisitionLength { get; set; }
+ ///
+ /// Gets the sample period in seconds
+ ///
+ /// The sample period in seconds
double SamplePeriod { get; }
+ ///
+ /// Gets the longest possible acquisition buffer (in seconds).
+ ///
double AcquisitionLengthMax { get; }
+ ///
+ /// Gets the shortest possible acquisition buffer (in seconds).
+ ///
double AcquisitionLengthMin { get; }
+
+ ///
+ /// Gets or sets the acquisition buffer depth (in samples)
+ ///
uint AcquisitionDepth { get; set; }
+ ///
+ /// Gets or sets the trigger hold off from the first sample of the acquisition buffer (in seconds)
+ ///
+ /// The trigger hold off.
double TriggerHoldOff { get; set; }
+ ///
+ /// Gets the trigger mode (Analog, digital or external)
+ ///
TriggerModes TriggerMode { get; }
+ ///
+ /// Gets or sets the analog trigger value
+ ///
+ /// The analog trigger value.
AnalogTriggerValue TriggerAnalog { get; set; }
+ ///
+ /// Sets the digital trigger
+ ///
+ /// The digital trigger.
Dictionary TriggerDigital { set; }
+ ///
+ /// Gets or sets the width of the trigger (in samples)
+ ///
+ /// The width of the trigger (in samples).
uint TriggerWidth { get; set; }
+ ///
+ /// Gets or sets the voltage threshold needed to cross before a trigger is considered valid
+ ///
+ /// The trigger threshold (volts).
float TriggerThreshold { get; set; }
+ ///
+ /// Gets or sets a value indicating whether this send overview buffer with each acquisition
+ ///
+ /// true if send overview buffer; otherwise, false.
bool SendOverviewBuffer { get; set; }
+ ///
+ /// Calling this results in a trigger force
+ ///
void ForceTrigger();
/* Channel specifics */
+ ///
+ /// Sets the coupling (AC or DC) for an analog input channel
+ ///
+ /// Channel.
+ /// Coupling (AC/DC).
void SetCoupling(AnalogChannel channel, Coupling coupling);
Coupling GetCoupling(AnalogChannel channel);
+ ///
+ /// Sets the voltage range of an analog input channel
+ ///
+ /// Channel.
+ /// Minimum.
+ /// Maximum.
void SetVerticalRange(AnalogChannel channel, float minimum, float maximum);
+ float[] GetVerticalRange(AnalogChannel channel);
+ ///
+ /// Sets the voltage offset of an analog input channel.
+ ///
+ /// WARNING: this offset is dicated by the vertical range. Check
+ /// GetYOffsetMax/Min() for the possible range
+ ///
+ /// Channel.
+ /// Offset.
void SetYOffset(AnalogChannel channel, float offset);
float GetYOffset(AnalogChannel channel);
+ ///
+ /// Gets the maximal voltage offset for the current voltage range
+ ///
+ /// Maximum voltage offset
+ /// Ch.
float GetYOffsetMax(AnalogChannel ch);
+ ///
+ /// Gets the minimal voltage offset for the current voltage range
+ ///
+ /// Minimum voltage offset
+ /// Ch.
float GetYOffsetMin(AnalogChannel ch);
+ ///
+ /// Sets the probe division (x1, x10, x100)
+ ///
+ /// Ch.
+ /// Division.
void SetProbeDivision(AnalogChannel ch, ProbeDivision division);
ProbeDivision GetProbeDivision(AnalogChannel ch);
/* Logic Analyser */
+ ///
+ /// Gets or sets a value indicating whether this 's logic analyser is enabled.
+ ///
+ /// true if logic analyser enabled; otherwise, false.
bool LogicAnalyserEnabled { get; set; }
+ ///
+ /// Which analog channel to discard to use for the logic analyser data
+ ///
+ /// The analog channel sacrificed for logic analyser data.
AnalogChannel ChannelSacrificedForLogicAnalyser { set; }
- /* Viewport */
+ /* Viewport */
+ ///
+ /// Sets the view port.
+ /// The viewport is the section of the acquisition buffer which is streamed to the host.
+ /// It is subsampled so that it fits within 2048 samples.
+ ///
+ /// When the scope is stopped, the acquisition buffer can be downloaded completely to the
+ /// host, without subsampling, but this can take several seconds. Instead, the viewport
+ /// can be changed when only interested in a section of the acquisition buffer, potentially
+ /// coarser than the effective sample rate.
+ ///
+ /// Offset of the first sample of the acquisition (in seconds)
+ /// Timespan of the viewport
void SetViewPort(double offset, double timespan);
double ViewPortTimeSpan { get; }
double ViewPortOffset { get; }
+ ///
+ /// Commits the settings to the device
+ ///
void CommitSettings();
}
diff --git a/Devices/SmartScope.cs b/Devices/SmartScope.cs
index 5e37822..b0ccddf 100644
--- a/Devices/SmartScope.cs
+++ b/Devices/SmartScope.cs
@@ -76,7 +76,7 @@ bool DiscardPreviousAcquisition
internal static double BASE_SAMPLE_PERIOD = 10e-9; //10MHz sample rate
private const int OVERVIEW_BUFFER_SIZE = 2048;
- private const int ACQUISITION_DEPTH_MIN = 128; //Size of RAM
+ private const int ACQUISITION_DEPTH_MIN = OVERVIEW_BUFFER_SIZE; //Size of RAM
private const int ACQUISITION_DEPTH_MAX = 512 * 1024;//4 * 1024 * 1024; //Size of RAM
private const int ACQUISITION_DEPTH_DEFAULT = 512 * 1024;
private const int BYTES_PER_BURST = 64;
@@ -296,7 +296,7 @@ private void CalibrateAdc()
SetTriggerByte(127);
LogicAnalyserEnabled = false;
Running = true;
- Logger.Info("Calibrating ADC timing");
+ Logger.Debug("Calibrating ADC timing");
CommitSettings();
//If the adc timing value is not the default (being 0, the first one in the list)
@@ -305,20 +305,20 @@ private void CalibrateAdc()
{
if (TestAdcRamp())
{
- Logger.Info("ADC calibration OK with value from ROM = " + AdcTimingValue);
+ Logger.Debug("ADC calibration OK with value from ROM = " + AdcTimingValue);
return;
}
}
foreach(byte timingValue in adcTimingValues)
{
- Logger.Info("Testing ADC timing value [" + timingValue + "]");
+ Logger.Debug("Testing ADC timing value [" + timingValue + "]");
AdcMemory[MAX19506.DATA_CLK_TIMING].Set(timingValue);
CommitSettings();
//Note: ForceTrigger won't work here yet since Ready is still false
if (TestAdcRamp())
{
- Logger.Info("ADC calibration OK with value " + timingValue);
+ Logger.Debug("ADC calibration OK with value " + timingValue);
AdcTimingValue = timingValue;
return;
}
@@ -402,7 +402,7 @@ private void Configure()
CalibrateAdc();
- Logger.Info("Found good ADC timing value [" + AdcTimingValue + "]");
+ Logger.Debug("Found good ADC timing value [" + AdcTimingValue + "]");
AcquisitionDepth = ACQUISITION_DEPTH_DEFAULT;
CommitSettings();
diff --git a/Devices/SmartScopeFlashHelpers.cs b/Devices/SmartScopeFlashHelpers.cs
index 82bc267..1488ef9 100644
--- a/Devices/SmartScopeFlashHelpers.cs
+++ b/Devices/SmartScopeFlashHelpers.cs
@@ -52,7 +52,7 @@ private bool FlashFpga ()
return false;
}
- Logger.Info("Got firmware of length " + firmware.Length);
+ Logger.Debug("Got firmware of length " + firmware.Length);
//Send FW to FPGA
try {
diff --git a/Devices/SmartScopeRom.cs b/Devices/SmartScopeRom.cs
index 12e20fc..c81e7cd 100644
--- a/Devices/SmartScopeRom.cs
+++ b/Devices/SmartScopeRom.cs
@@ -112,6 +112,36 @@ public GainCalibration getCalibration(AnalogChannel ch, double divider, double m
return gainCalibration.Where(x => x.channel == ch && x.divider == divider && x.multiplier == multiplier).First();
}
+ private void ByteSwap(byte[] b, Type t)
+ {
+ if (BitConverter.IsLittleEndian)
+ return;
+ foreach (var field in t.GetFields())
+ {
+ int subsize = 0;
+ foreach (var subField in field.FieldType.GetFields())
+ {
+ if (!subField.IsStatic)
+ subsize = Marshal.SizeOf(subField.FieldType);
+ }
+ var offs = Marshal.OffsetOf(t, field.Name).ToInt32();
+ var size = Marshal.SizeOf(field.FieldType);
+ int count = 1;
+ if (subsize > 0) {
+ count = size / subsize;
+ size = subsize;
+ }
+ if (size > 1)
+ {
+ for (uint i = 0; i < count; i++)
+ {
+ Array.Reverse(b, offs, size);
+ offs += size;
+ }
+ }
+ }
+ }
+
private byte[] MapToBytes(Map m)
{
int size = Marshal.SizeOf(m);
@@ -120,6 +150,7 @@ private byte[] MapToBytes(Map m)
Marshal.StructureToPtr(m, p, true);
Marshal.Copy(p, output, 0, size);
+ ByteSwap(output, typeof(Map));
Marshal.FreeHGlobal(p);
return output;
}
@@ -129,6 +160,7 @@ private Map BytesToMap(byte[] b)
Map m = new Map();
int size = Marshal.SizeOf(m);
IntPtr ptr = Marshal.AllocHGlobal(size);
+ ByteSwap(b, typeof(Map));
Marshal.Copy(b, 0, ptr, size);
m = (Map)Marshal.PtrToStructure(ptr, m.GetType());
diff --git a/Devices/SmartScopeSettings.cs b/Devices/SmartScopeSettings.cs
index f8d47d7..eeb50ac 100644
--- a/Devices/SmartScopeSettings.cs
+++ b/Devices/SmartScopeSettings.cs
@@ -169,6 +169,11 @@ public float GetYOffset(AnalogChannel channel)
public float GetYOffsetMax(AnalogChannel channel) { return ConvertYOffsetByteToVoltage(channel, yOffsetMax); }
public float GetYOffsetMin(AnalogChannel channel) { return ConvertYOffsetByteToVoltage(channel, yOffsetMin); }
+
+ //The voltage range for div/mul = 1/1
+ float baseVoltageRangeMin = -0.6345f; //V
+ float baseVoltageRangeMax = 0.6769f; //V
+
///
/// Sets and uploads the divider and multiplier what are optimal for the requested range
///
@@ -178,11 +183,7 @@ public float GetYOffset(AnalogChannel channel)
public void SetVerticalRange(AnalogChannel channel, float minimum, float maximum)
{
if (!Connected) return;
- //The voltage range for div/mul = 1/1
- //20140808: these seem to be OK: on div0/mult0 the ADC input range is approx 1.3V
- float baseMin = -0.6345f; //V
- float baseMax = 0.6769f; //V
-
+
//Walk through dividers/multipliers till requested range fits
//this walk assumes it starts with the smallest range, and that range is only increasing
int dividerIndex = 0;
@@ -195,9 +196,9 @@ public void SetVerticalRange(AnalogChannel channel, float minimum, float maximum
dividerIndex= i / rom.computedMultipliers.Length;
multIndex = rom.computedMultipliers.Length - (i % rom.computedMultipliers.Length) - 1;
if (
- (ProbeScaleHostToScope(channel, maximum) < baseMax * rom.computedDividers[dividerIndex] / rom.computedMultipliers[multIndex])
+ (ProbeScaleHostToScope(channel, maximum) < baseVoltageRangeMax * rom.computedDividers[dividerIndex] / rom.computedMultipliers[multIndex])
&&
- (ProbeScaleHostToScope(channel, minimum) > baseMin * rom.computedDividers[dividerIndex] / rom.computedMultipliers[multIndex])
+ (ProbeScaleHostToScope(channel, minimum) > baseVoltageRangeMin * rom.computedDividers[dividerIndex] / rom.computedMultipliers[multIndex])
)
break;
}
@@ -212,6 +213,16 @@ public void SetVerticalRange(AnalogChannel channel, float minimum, float maximum
//SetTriggerThreshold(this.triggerThreshold);
}
}
+ public float[] GetVerticalRange(AnalogChannel channel)
+ {
+ int dividerIndex = Array.IndexOf (validDividers, channelSettings [channel].divider);
+ int multIndex = Array.IndexOf (validMultipliers, channelSettings [channel].multiplier);
+ return new float[] {
+ ProbeScaleScopeToHost(channel, (float)(baseVoltageRangeMin * rom.computedDividers[dividerIndex] / rom.computedMultipliers[multIndex])),
+
+ ProbeScaleScopeToHost(channel, (float)(baseVoltageRangeMax * rom.computedDividers[dividerIndex] / rom.computedMultipliers[multIndex]))
+ };
+ }
public void SetProbeDivision(AnalogChannel ch, ProbeDivision division)
{
diff --git a/Hardware/InterfaceManagerLibUsb.cs b/Hardware/InterfaceManagerLibUsb.cs
index a6d3f4f..bbf1822 100644
--- a/Hardware/InterfaceManagerLibUsb.cs
+++ b/Hardware/InterfaceManagerLibUsb.cs
@@ -133,7 +133,7 @@ private void DeviceFound(LibUsbDotNet.UsbDevice scopeUsbDevice)
Common.Logger.Warn("Can't re-register device with this serial " + serial);
throw new ScopeIOException("This device was already registered. This is a bug");
}
- C.Logger.Warn("Device found with serial [" + serial + "]");
+ C.Logger.Debug("Device found with serial [" + serial + "]");
interfaces.Add(serial, f);
if (onConnect != null)
@@ -156,7 +156,7 @@ private void OnDeviceNotifyEvent(object sender, DeviceNotifyEventArgs e)
C.Logger.Debug("LibUSB device arrival");
if (e.Device == null || e.Device.IdVendor != VID || !PIDs.Contains(e.Device.IdProduct))
{
- C.Logger.Info("Not taking this device, PID/VID not a smartscope");
+ C.Logger.Debug("Not taking this device, PID/VID not a smartscope");
return;
}