Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for AWG? #2

Open
MGlolenstine opened this issue Mar 19, 2021 · 7 comments
Open

Support for AWG? #2

MGlolenstine opened this issue Mar 19, 2021 · 7 comments
Labels
enhancement New feature or request

Comments

@MGlolenstine
Copy link

MGlolenstine commented Mar 19, 2021

Is there any support for Arbitrary Waveform Generator?
All I've seen is Streaming for incoming data, and I only see 2 channels being shown (A, B) on my 2204A.

I've skimmed through most of the crates in this repo but haven't seen a way of using the AWG.

EDIT:
More information about the AWG can be seen at 2.11.47 here.
People seem to be calling it directly from the dll.

@timfish
Copy link
Owner

timfish commented Mar 19, 2021

Yes, all that's currently implemented is continuous streaming.

First I need to merge these changes which:

  • Uses bindgen generated wrappers for every oscilloscope driver rather than manual wrappers
  • Adds safe wrappers for every driver implementing the PicoDriver trait
  • Adds support for new 6000A driver
  • Improves streaming state machine
  • Ergonomic improvements

Once thats merged all the SigGen/AWG features will be available like this.

After that, support for SigGen/AWG would be added by:

  • Decide on common settings/interface across all Pico drivers
  • Extending PicoDriver with above interface
  • Updating all the safe wrappers with changes from above

@MGlolenstine
Copy link
Author

Oooh, I see!
I did see the improvements branch but didn't really skim through it.

The bindgen will be much better than writing those wrappers by hand for sure.

@timfish
Copy link
Owner

timfish commented Mar 19, 2021

We can leave this issue open and close it when the AWG is fully supported!

@timfish timfish reopened this Mar 19, 2021
@timfish timfish added the enhancement New feature or request label Mar 31, 2021
@alon
Copy link

alon commented Apr 7, 2022

Hi,

I've taken a stab at adding AWG, so far I'm getting errors when trying to grab the handle, but those appear to be my misunderstanding about getting a handle from driver and using streaming at the same time.

Is this something that is already being worked on? The PR mentioned above has been merged it seems.

Alon

p.s. A bit preliminary to do a PR, because it still doesn't run (or rather my test code cannot do streaming and call this at the same time since when I do driver.handle.lock().take() it causes the following streaming operation to fail with NOT_FOUND),
but any guidelines based on the following would be appreciated.

commit 45a98edc8edf22a08b04cce175aa31999afe4ebc
Author: Alon Levy <[email protected]>
Date:   Thu Apr 7 13:56:14 2022 +0300

    add call to ps2000aSetSigGenArbitrary via PicoDriver::set_sig_gen_arbitrary

diff --git a/common/src/enums.rs b/common/src/enums.rs
index 1250e1e..55c7678 100644
--- a/common/src/enums.rs
+++ b/common/src/enums.rs
@@ -214,3 +214,103 @@ impl From<PicoInfo> for i16 {
         num_traits::ToPrimitive::to_i16(&value).expect("Non-valid info type")
     }
 }
+
+#[derive(Debug, Clone, Copy, FromPrimitive, ToPrimitive)]
+pub enum PicoSweepType
+{
+        SweepUp = 0,
+        SweepDown = 1,
+        SweepUpDown = 2,
+        SweepDownUp = 3,
+}
+
+#[derive(Debug, Clone, Copy, FromPrimitive, ToPrimitive)]
+pub enum PicoExtraOperations
+{
+        /// <summary>
+        /// Normal signal generator operation specified by wavetype.
+        /// </summary>
+        ExtraOperationsOff = 0,
+        /// <summary>
+        /// The signal generator produces white noise and ignores all settings except pkToPk and offsetVoltage.
+        /// </summary>
+        ExtraOperationsWhiteNoise = 1,
+        /// <summary>
+        /// produces a pseudorandom random binary sequence with a bit rate
+        /// specified by the start and stop frequency.
+        /// </summary>
+        ExtraOperationsPRBS = 2, // Pseudo-Random Bit Stream
+}
+
+/// <summary>
+/// AWG index modes
+/// </summary>
+#[derive(Debug, Clone, Copy, FromPrimitive, ToPrimitive)]
+pub enum PicoIndexMode
+{
+        /// <summary>
+        /// The generator outputs the raw contents of the buffer repeatedly .
+        /// </summary>
+        IndexModeSingle = 0,
+        /// <summary>
+        /// The generator outputs the contents of the buffer from beginning to end, and then does a second pass in the reverse
+        /// direction through the buffer
+        /// </summary>
+        IndexModeDual = 1,
+        /// <summary>
+        /// This is similiar to the Dual but passes through the buffer four time inverting, and inverting reversed
+        /// </summary>
+        IndexModeQuad = 2,
+}
+
+/// <summary>
+/// The type of trigger that will be applied to the signal generator
+/// </summary>
+#[derive(Debug, Clone, Copy, FromPrimitive, ToPrimitive)]
+pub enum PicoSigGenTrigType
+{
+        /// <summary>
+        /// Trigger on rising edge
+        /// </summary>
+        SigGenTrigTypeRising = 0,
+        /// <summary>
+        /// Trigger on falling edge
+        /// </summary>
+        SigGenTripTypeFalling = 1,
+        /// <summary>
+        /// Run while trigger is high
+        /// </summary>
+        SigGenTrigTypeGateHigh = 2,
+        /// <summary>
+        /// Run while trigger is low
+        /// </summary>
+        SigGenTrigTypeGateLow = 3,
+}
+
+/// <summary>
+/// The source that will trigger the signal generator
+/// </summary>
+#[derive(Debug, Clone, Copy, FromPrimitive, ToPrimitive)]
+pub enum PicoSigGenTrigSource
+{
+        /// <summary>
+        /// Run without waiting for trigger
+        /// </summary>
+        SigGenTrigSourceNone = 0,
+        /// <summary>
+        /// Use scope trigger
+        /// </summary
+        SigGenTrigSourceScopeTrig = 1,
+        /// <summary>
+        /// Use AUXIO input
+        /// </summary>
+        SigGenTrigSourceAuxIn = 2,
+        /// <summary>
+        /// Use external input
+        /// </summary>
+        SigGenTrigSourceExtIn = 3,
+        /// <summary>
+        /// Wait for software trigger
+        /// </summary>
+        SigGenTrigSourceSoftTrig = 4,
+}
\ No newline at end of file
diff --git a/driver/src/lib.rs b/driver/src/lib.rs
index 523851c..c4f3832 100644
--- a/driver/src/lib.rs
+++ b/driver/src/lib.rs
@@ -44,10 +44,8 @@
 #![allow(clippy::upper_case_acronyms)]
 
 use parking_lot::RwLock;
-use pico_common::{
-    ChannelConfig, Driver, FromPicoStr, PicoChannel, PicoError, PicoInfo, PicoRange, PicoResult,
-    SampleConfig,
-};
+use pico_common::{ChannelConfig, Driver, FromPicoStr, PicoChannel, PicoError, PicoInfo, PicoRange, PicoResult, SampleConfig,
+                  PicoSweepType, PicoExtraOperations, PicoIndexMode, PicoSigGenTrigType, PicoSigGenTrigSource};
 pub use resolution::Resolution;
 use std::{fmt, pin::Pin, sync::Arc};
 use thiserror::Error;
@@ -159,6 +157,28 @@ pub trait PicoDriver: fmt::Debug + Send + Sync {
             Ok(())
         }
     }
+
+     fn set_sig_gen_arbitrary(
+        &self,
+        _handle: i16,
+        _offset_voltage: i32,
+        _pk_to_pk: u32,
+        _start_delta_phase: u32,
+        _stop_delta_phase: u32,
+        _delta_phase_increment: u32,
+        _dwell_count: u32,
+        _arbitrary_waveform: &Vec<i16>,
+        _sweep_type: PicoSweepType,
+        _operation: PicoExtraOperations,
+        _index_mode: PicoIndexMode,
+        _shots: u32,
+        _sweeps: u32,
+        _trigger_type: PicoSigGenTrigType,
+        _trigger_source: PicoSigGenTrigSource,
+        _ext_in_threshold: i16,
+     ) ->  PicoResult<()> {
+         unimplemented!()
+     }
 }
 
 pub type ArcDriver = Arc<dyn PicoDriver>;
diff --git a/driver/src/ps2000a.rs b/driver/src/ps2000a.rs
index 252ff67..328a841 100644
--- a/driver/src/ps2000a.rs
+++ b/driver/src/ps2000a.rs
@@ -5,11 +5,9 @@ use crate::{
     EnumerationResult, PicoDriver,
 };
 use parking_lot::RwLock;
-use pico_common::{
-    ChannelConfig, DownsampleMode, Driver, FromPicoStr, PicoChannel, PicoError, PicoInfo,
-    PicoRange, PicoResult, PicoStatus, SampleConfig, ToPicoStr,
-};
-use pico_sys_dynamic::ps2000a::PS2000ALoader;
+use pico_common::{ChannelConfig, DownsampleMode, Driver, FromPicoStr, PicoChannel, PicoError, PicoInfo, PicoRange, PicoResult, PicoStatus, SampleConfig, ToPicoStr,
+                  PicoSweepType, PicoExtraOperations, PicoIndexMode, PicoSigGenTrigType, PicoSigGenTrigSource};
+use pico_sys_dynamic::ps2000a::{PS2000A_EXTRA_OPERATIONS, PS2000A_INDEX_MODE, PS2000A_SIGGEN_TRIG_SOURCE, PS2000A_SIGGEN_TRIG_TYPE, PS2000A_SWEEP_TYPE, PS2000ALoader};
 use std::{pin::Pin, sync::Arc};
 
 pub struct PS2000ADriver {
@@ -280,4 +278,51 @@ impl PicoDriver for PS2000ADriver {
     fn stop(&self, handle: i16) -> PicoResult<()> {
         PicoStatus::from(unsafe { self.bindings.ps2000aStop(handle) }).to_result((), "stop")
     }
+
+    #[tracing::instrument(level = "trace", skip(self))]
+    fn set_sig_gen_arbitrary(
+        &self,
+        handle: i16,
+        offset_voltage: i32,
+        pk_to_pk: u32,
+        start_delta_phase: u32,
+        stop_delta_phase: u32,
+        delta_phase_increment: u32,
+        dwell_count: u32,
+        arbitrary_waveform: &Vec<i16>,
+        sweep_type: PicoSweepType,
+        operation: PicoExtraOperations,
+        index_mode: PicoIndexMode,
+        shots: u32,
+        sweeps: u32,
+        trigger_type: PicoSigGenTrigType,
+        trigger_source: PicoSigGenTrigSource,
+        ext_in_threshold: i16,
+     ) ->  PicoResult<()> {
+        // TODO: no idea how to do this better
+        // to avoid the data being taken away, store a copy here?
+        // go read the SDK to see if the memory is caller responsibility or
+        // copied by the library.
+        let mut arbitrary_waveform = arbitrary_waveform.clone();
+         PicoStatus::from(unsafe {
+             self.bindings.ps2000aSetSigGenArbitrary(
+                 handle,
+                 offset_voltage,
+                 pk_to_pk,
+                 start_delta_phase,
+                 stop_delta_phase,
+                 delta_phase_increment,
+                 dwell_count,
+                 arbitrary_waveform.as_mut_ptr(),
+                 arbitrary_waveform.len() as i32,
+                 sweep_type as PS2000A_SWEEP_TYPE,
+                 operation as PS2000A_EXTRA_OPERATIONS,
+                 index_mode as PS2000A_INDEX_MODE,
+                 shots,
+                 sweeps,
+                 trigger_type as PS2000A_SIGGEN_TRIG_TYPE,
+                 trigger_source as PS2000A_SIGGEN_TRIG_SOURCE,
+                 ext_in_threshold)
+         }).to_result((), "set_sig_gen_arbitrary")
+     }
 }

@timfish
Copy link
Owner

timfish commented Apr 7, 2022

Hi @alon,

No, I have started looking at the AWG yet. Even though I have experience with every Pico driver, I have never implemented AWG features!

My understanding of how the Pico devices work, and observing them in PicoScope is that you cannot modify the AWG settings while streaming is in progress. You need to configure before streaming starts and if you want to modify the settings later, you need to stop capture, modify AWG settings and then start streaming again.

@timfish
Copy link
Owner

timfish commented Apr 7, 2022

I have access to most Pico devices so if you get stuck, link to a repository and I'll be happy to take a look!

@alon
Copy link

alon commented Apr 7, 2022 via email

@alon alon mentioned this issue Apr 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants