import pyvisa
from enum import Enum
from typing import List
import sys




class State(Enum):
    OFF = 0
    ON = 1

class Pod(Enum):
    PodA = 1
    PodB = 2
    PodC = 3
    PodD = 4

class GetValue(Enum):
    PRESENT = ""
    MAXIMUM = "MAXimum"
    MINIMUM = "MINimum"

class SetValue(Enum):
    PRESENT = ""
    MAXIMUM = "MAX"
    MINIMUM = "MIN"
    DEFAULT = "DEF"

class SetValue2(Enum):
    PRESENT = ""
    MAXIMUM = "MAX"
    MINIMUM = "MIN"
    DEFAULT = "DEF"
    INFINITE = "INF"

class ChannelsNumber(Enum):
    Zero = 0
    Eight = 8
    Sixteen = 16
    Twentyfour = 24
    Thirtytwo = 32

class Marker(Enum):
    Marker1 = 1
    Marker2 = 2
    Marker3 = 3
    Marker4 = 4

class MarkerMode(Enum):
    Fixed_Low = "FIXEDLow"
    Fixed_High = "FIXEDHigh"
    Automatic = "AUTO"
    Custom_Pattern = "CUSTOMPattern"

class Channel(Enum):
    Channel1 = 1
    Channel2 = 2
    Channel3 = 3
    Channel4 = 4
    Channel5 = 5
    Channel6 = 6
    Channel7 = 7
    Channel8 = 8

class ChannelEntry(Enum):
    Channel1 = 1
    Channel2 = 2
    Channel3 = 3
    Channel4 = 4
    Channel5 = 5
    Channel6 = 6
    Channel7 = 7
    Channel8 = 8
    ProgrammedMarker = 9
    Digital = 10

class KeepLastMode(Enum):
    CustomOnStop = "OFF"
    KeepLast = "ON"

class Polarity(Enum):
    Normal = "NORM"
    Inverted = "INV"

class AutoCalcOption(Enum):
    Length = "LENgth"
    SamplingRate = "SPRate"
    Cycles = "CYCles"
    LengthAndCycles = "LENGTHCycles"
    Frequency = "FREQuency"

class ExpMode(Enum):
    Rise = "RISe"
    Decay = "DECay"

class PRBSType(Enum):
    PRBS7 = 7
    PRBS9 = 9
    PRBS11 = 11
    PRBS15 = 15
    PRBS23 = 23
    PRBS31 = 31

class WaveType(Enum):
    Sine = "SINe"
    Pulse = "PULse"
    Sweep = "SWEep"
    Sinc = "SINc"
    Exponential = "EXP"
    PRBS = "PRBs"
    Square = "SQUare"
    Multitone = "MULtitone"

class SweepMode(Enum):
    Linear = "LIN"
    Logarithmic = "LOG"

class Tone(Enum):
    Tone1 = 1
    Tone2 = 2
    Tone3 = 3
    Tone4 = 4
    Tone5 = 5
    Tone6 = 6
    Tone7 = 7
    Tone8 = 8
    Tone9 = 9
    Tone10 = 10

class SpecificOrAll(Enum):
    Specific = 1
    All = "ALL"

class WaveformAttribute(Enum):
    NotPredefined = "NOTP"
    Predefined = "PRE"

class DecreasingStrategy(Enum):
    Decimation = "DECIM"
    CutTail = "CUTT"
    CutHead = "CUTH"

class IncreasingStrategy(Enum):
    Interpolation = "INTER"
    ReturnZero = "RETURN"
    HoldLast = "HOLD"
    SamplesMultiplication = "SAMPLESM"

class BurstSelection(Enum):
    NumberCycles = ""
    Default = "DEF"
    Minimum = "MIN"
    Maximum = "MAX"

class JumpMode(Enum):
    AfterRepetitions = "AFTER"
    ASAP = "IMM"

class RunMode(Enum):
    Continuous = "CONT"
    SingleBurst = "BURSt"
    Triggered = "TCON"
    Stepped = "STEP"
    Advanced = "ADVA"

class WaitTriggerState(Enum):
    First_sample = "FIRST"
    Last_sample = "LAST"

class Mode(Enum):
    First = "FIRST"
    Previous = "PREV"
    Next = "NEXT"
    Last = "LAST"
    Item = "ITEM"

class JumpEvent(Enum):
    NONE = "NONE"
    Button = "MAN"
    Timer = "TIM"
    ExtTrig1 = "EXTernal1"
    ExtTrig2 = "EXTernal2"
    ExtTrig3 = "EXTernal3"
    ExtTrig4 = "EXTernal4"

class SequencerLengthStrategy(Enum):
    AdaptToLongerAnalogWaveform = "ADAPTL"
    AdaptToShorterAnalogWaveform = "ADAPTS"
    Default = "DEF"

class ClockSource(Enum):
    Internal = "INT"
    External = "EXTCLK"
    Reference = "REFCLK"

class ExtClkDivisor(Enum):
    Two = 2
    Four = 4
    Eight = 8
    Sixteen = 16
    Thirtytwo = 32

class SyncClockOutSelector(Enum):
    One = 1
    Two = 2
    Three = 3
    Four = 4
    Five = 5
    Six = 6
    Seven = 7
    Eight = 8

class TriggerIn(Enum):
    TriggerIn1 = 1
    TriggerIn2 = 2
    TriggerIn3 = 3
    TriggerIn4 = 4

class Impedance(Enum):
    High = "1KOhm"
    Normal = "50Ohm"

class Slope(Enum): 
    Positive = "POS"
    Negative = "NEG"
    Both = "BOTH"

class TriggerInSource(Enum):
    ExtTriggerIn = "EXT"
    Timer = "TIMER"
    Button = "MAN"

class TriggerTiming(Enum):
    Slow = "OFF"
    Fast = "ON"

class WaveformType(Enum):
    Analog = "ANA"
    Digital = "DIG"

class Memory(Enum):
    Memory0 = 0
    Memory1 = 1
    Memory2 = 2
    Memory3 = 3
    Memory4 = 4
    Configuration = 5

class App(Enum):
    Function = "FG"
    Pattern = "DPG"

class Format(Enum):
    Amplitude_offset = "AMPLitudeoff"
    Vhigh_Vlow = "HIGHlow"

class Carrier(Enum):
    Carrier0 = 1
    Carrier1 = 2

class Component(Enum):
    InPhaseI0 = 1
    QuadratureQ0 = 2
    InPhaseI1 = 3
    QuadratureQ1 = 4

class CMLVoltageLevel(Enum):
    mV590 = "590"
    mV730 = "730"
    mV870 = "870"
    mV980 = "980"

class ChannelOptimization(Enum):
    Low_Noise = "LOWN"
    High_Linearity = "HLIN"

class OperatingMode(Enum):
    Full_rate = "FULLR"
    Half_rate = "HALFR"
    Full_rate_short_mem = "FULLRATES"

class OutputFormat(Enum):
    Waveform = 0
    Take_last = 1

class SequencerEntry():
    def __init__(self, entry_number: int, analog_waveform_names: List[str], amplitudes: List[float], offsets: List[float], decreasing_strategies: List[DecreasingStrategy],
                 increasing_strategies: List[IncreasingStrategy], sub_lengths: List[int], delays: List[float], digital_waveform_name: str, custom_pattern: str,
                 length: int, repetitions: int, output_formats: List[OutputFormat]):
        """Parameters must be listed like: waveform_names = [name_Ch1, name_Ch2, ..., name_Chn]"""
        self.entry_number = entry_number
        self.analog_waveform_names = analog_waveform_names
        self.amplitudes = amplitudes
        self.offsets = offsets
        self.decreasing_strategies = decreasing_strategies
        self.increasing_strategies = increasing_strategies
        self.sub_lengths = sub_lengths
        self.delays = delays
        self.digital_waveform_name = digital_waveform_name
        self.custom_pattern = custom_pattern
        self.length = length
        self.repetitions = repetitions
        self.output_formats = output_formats

class AdvancedSequencerEntry():
    def __init__(self, entry_number: int, analog_waveform_names: List[str], amplitudes: List[float], offsets: List[float], decreasing_strategies: List[DecreasingStrategy],
                    increasing_strategies: List[IncreasingStrategy], sub_lengths: List[int], delays: List[float], digital_waveform_name: str, custom_pattern: str,
                    length: int, repetitions: int, output_formats: List[OutputFormat], wait_event: JumpEvent, jump_event: JumpEvent, jump_to_mode: JumpMode,
                    jump_to_entry_item: int, pattern_code: int, pattern_mode: JumpMode, pattern_jump_to_entry: int, go_to_mode: JumpMode, go_to_entry_item: int):
        """Parameters must be listed like: waveform_names = [name_Ch1, name_Ch2, ..., name_Chn]"""
        self.entry_number = entry_number
        self.analog_waveform_names = analog_waveform_names
        self.amplitudes = amplitudes
        self.offsets = offsets
        self.decreasing_strategies = decreasing_strategies
        self.increasing_strategies = increasing_strategies
        self.sub_lengths = sub_lengths
        self.delays = delays
        self.digital_waveform_name = digital_waveform_name
        self.custom_pattern = custom_pattern
        self.length = length
        self.repetitions = repetitions
        self.output_formats = output_formats
        self.wait_event = wait_event
        self.jump_event = jump_event
        self.jump_to_mode = jump_to_mode
        self.jump_to_entry_item = jump_to_entry_item
        self.pattern_code = pattern_code
        self.pattern_mode = pattern_mode
        self.pattern_jump_to_entry = pattern_jump_to_entry
        self.go_to_mode = go_to_mode
        self.go_to_entry_item = go_to_entry_item








class AWG7000():
    def __init__(self, instrument: pyvisa.resources.tcpip.TCPIPInstrument, error_control=True):
        """This class can be used to send instruction to any AWG5000 by Active TRechnologies.
            ARGS: instrument: TCP/IP address of the instrument;
                number of channels: instruement number of channels.
                error_control: set this flag to true to manage possible exceptions thrown by query or write. The code will be slower"""
        self.instrument = instrument
        self.error_control = error_control
        self.channels: List[Channel]
        self.model: str
        self.number_of_channels: int
        self.number_of_markers: int

    def Close(self):
        self.instrument.close()
    
    def ErrorQuery(self):
        try: return self.instrument.query(f"SYST:ERR?")
        except Exception as e: print(f"Was not able to receive error message from intrument because of the following error: {e}")
    
    #Write and query methods with exception management
    def CheckWrite(self, string: str):
        if self.error_control:
            try:
                self.instrument.write(string)
            except Exception as e: raise Exception(e)
            else:
                error: str = self.ErrorQuery()
                if not error.startswith("0"): raise Exception(error)
        else: self.instrument.write(string)

    def CheckQuery(self, string: str):
        if self.error_control:
            try:
                result: str = self.instrument.query(string)
            except Exception as e: raise Exception(e)
            else:
                error: str = self.ErrorQuery()
                if not error.startswith("0"): raise Exception(error)
                else: return result
        else: return self.instrument.query(string)

    
    #ACTION STATUS
    def AWGStart(self):
        self.CheckWrite("AWGControl:RUN")
    
    def AWGStop(self):
        self.CheckWrite("AWGControl:STOP")
    
    def GetAWGStatus(self):
        return self.CheckQuery("AWGControl:RSTATe?")
    
    def GetDigitalState(self):
        return self.CheckQuery("DIGitals:STATe?")
    
    def GetOutputState(self, channel: int):
        return self.CheckQuery(f"OUTPut{channel}:STATe?")
    
    def SendTrigger(self):
        self.CheckWrite("*TRG")
    
    def ReleaseTrigger(self):
        self.CheckWrite("ABORt")

    def SendForcedJump(self, entry: int):
        self.CheckWrite(f"AWGControl:DJump:FORce {entry}")

    def SendPatternCode(self, pattern_code: int):
        self.CheckWrite(f"AWGControl:DJStrobe {pattern_code}")
    
    def SetDigitalsState(self, state: State):
        return self.CheckWrite(f"DIGitals:STATe {state.value}")
    
    def SetOutputState(self, channel: Channel, state: State): 
        self.CheckWrite(f"OUTPut{channel.value}:STATe {state.value}")

    def Initialize(self, reset: bool = False, ID_query: bool = True):
        try:
            self.instrument.timeout = 180000
            self.CheckWrite("*CLS")
            if ID_query == True:
                ID = self.CheckQuery("*IDN?")
                possible_IDs = ["ACTIVE TECHNOLOGIES,AWG7202,", "ACTIVE TECHNOLOGIES,AWG7202D,", "ACTIVE TECHNOLOGIES,AWG7172,", "ACTIVE TECHNOLOGIES,AWG7172D,",
                                "ACTIVE TECHNOLOGIES,AWG7102,", "ACTIVE TECHNOLOGIES,AWG7102D,", "ACTIVE TECHNOLOGIES,AWG7204,", "ACTIVE TECHNOLOGIES,AWG7204D,",
                                "ACTIVE TECHNOLOGIES,AWG7174,", "ACTIVE TECHNOLOGIES,AWG7174D,", "ACTIVE TECHNOLOGIES,AWG7104,", "ACTIVE TECHNOLOGIES,AWG7104D,",
                                "ACTIVE TECHNOLOGIES,AWG7204S,", "ACTIVE TECHNOLOGIES,AWG7204DS,", "ACTIVE TECHNOLOGIES,AWG7174S,", "ACTIVE TECHNOLOGIES,AWG7172DS,",
                                "ACTIVE TECHNOLOGIES,BAWG7202,", "ACTIVE TECHNOLOGIES,BAWG7202D,", "ACTIVE TECHNOLOGIES,BAWG7204,", "ACTIVE TECHNOLOGIES,BAWG7204D,"]
                for i in range(len(possible_IDs)):
                    if ID.startswith(possible_IDs[i]):
                        self.model = possible_IDs[i]
                        if i in [0, 1, 2, 3, 4, 5, 16, 17]:
                            self.number_of_channels = 2
                            self.channels = [Channel.Channel1, Channel.Channel2]
                            self.number_of_markers = 2
                        else:
                            self.number_of_channels = 4
                            self.channels = [Channel.Channel1, Channel.Channel2, Channel.Channel3, Channel.Channel4]
                            self.number_of_markers = 4
                        if reset == True: self.Reset()
                        break
                    elif i == 19: raise Exception("Initialization failed: instrument ID not found")
            else:
                self.number_of_channels = 2
                self.channels = [Channel.Channel1, Channel.Channel2]
                self.number_of_markers = 2
        except Exception as e:
            self.Close()
            raise Exception(e)



    
    #BASIC
    #Digitals
    def GetDigitalChannelsNumber(self):
        return self.CheckQuery(f"DIGitals:NUMber?")
    
    def SetDigitalChannelsNumber(self, channels_number: ChannelsNumber):
        self.CheckWrite(f"DIGitals:NUMber {channels_number.value}")
    
    def GetDigitalPodCMLVoltageLevel(self, digital_pod: Pod):
        return self.CheckQuery(f"DIGitals:CMLLevel{digital_pod.value}?")
    
    def SetDigitalPodCMLVoltageLevel(self, digital_pod: Pod, voltage_level: CMLVoltageLevel):
        self.CheckWrite(f"DIGitals:LEVel{digital_pod.value} {voltage_level.value}")

    def GetDigitalPodCMLEqualizationFactor(self, digital_pod: Pod, minmax: GetValue):
        return self.CheckQuery(f"DIGitals:CMLEQFactor{digital_pod.value}? {minmax.value}")
    
    def SetDigitalPodCMLEqualizationFactor(self, digital_pod: Pod, equalization_factor: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"DIGitals:CMLEQFactor{digital_pod.value} {equalization_factor}")
        else: self.CheckWrite(f"DIGitals:CMLEQFactor{digital_pod.value} {minmax.value}")

    def GetDigitalPodDTTLLevel(self, digital_pod: Pod, minmax: GetValue):
        return self.CheckQuery(f"DIGitals:LEVel{digital_pod.value}? {minmax.value}")
    
    def SetDigitalPodDTTLLevel(self, digital_pod: Pod, voltage_level: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"DIGitals:LEVel{digital_pod.value} {voltage_level}")
        else: self.CheckWrite(f"DIGitals:LEVel{digital_pod.value} {minmax.value}")

    def GetDigitalPodSkew(self, digital_pod: Pod, minmax: GetValue):
        return self.CheckQuery(f"LEVel:SKEW{digital_pod.value}? {minmax.value}")
    
    def SetDigitalPodSkew(self, digital_pod: Pod, skew: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"DIGitals:SKEW{digital_pod.value} {skew}")
        else: self.CheckWrite(f"DIGitals:LEVel{digital_pod.value} {minmax.value}")

    #Marker out
    def GetMarkerHighVoltage(self, marker: Marker, minmax: GetValue):
        return self.CheckQuery(f"MARKer:LEVel{marker.value}?  {minmax.value}")
    
    def SetMarkerHighVoltage(self, marker: Marker, high_voltage: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"MARKer:LEVel{marker.value} {high_voltage}")
        else: self.CheckWrite(f"MARKer:LEVel{marker.value} {minmax.value}")

    def GetMarkerLowVoltage(self, marker: Marker, minmax: GetValue):
        return self.CheckQuery(f"MARKer:LLEVel{marker.value}?  {minmax.value}")
    
    def SetMarkerLowVoltage(self, marker: Marker, low_voltage: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"MARKer:LLEVel{marker.value} {low_voltage}")
        else: self.CheckWrite(f"MARKer:LLEVel{marker.value} {minmax.value}")

    def GetMarkerMode(self, marker: Marker):
        return self.CheckQuery(f"MARKer:MODE{marker.value}?")
    
    def SetMarkerMode(self, marker: Marker, mode: MarkerMode):
        self.CheckWrite(f"MARKer:MODE{marker.value} {mode.value}")

    def GetMarkerSkew(self, marker: Marker, minmax: GetValue):
        return self.CheckQuery(f"MARKer:SKEW{marker.value}? {minmax.value}")
    
    def SetMarkerSkew(self, marker: Marker, skew: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"MARKer:SKEW{marker.value} {skew}")
        else: self.CheckWrite(f"MARKer:SKEW{marker.value} {minmax.value}")

    #Output Options
    def GetValueOnStopStateSingleEnded(self, channel: Channel):
        return self.CheckQuery(f"OUTPut{channel.value}:BLOFfset:KEEPLast?")
    
    def SetValueOnStopStateSingleEnded(self, channel: Channel, mode: KeepLastMode):
        self.CheckWrite(f"OUTPut{channel.value}:BLOFfset:KEEPLast {mode.value}")

    def GetBaseLineOffset(self, channel: Channel, minmax: GetValue):
        return self.CheckQuery(f"OUTPut{channel.value}:BLOFfset? {minmax.value}")
    
    def SetBaselineOffset(self, channel: Channel, baseline_offset: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"OUTPut{channel.value}:BLOFfset {baseline_offset}")
        else: self.CheckWrite(f"OUTPut{channel.value}:BLOFfset {minmax.value}")

    def GetStoppedValueSingleEndedOut(self, channel: Channel, minmax: GetValue):
        return self.CheckQuery(f"OUTPut{channel.value}:BLOFfset:CUSTOMValue? {minmax.value}")
    
    def SetStoppedValueSingleEndedOut(self, channel: Channel, baseline_offset_on_stop: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"OUTPut{channel.value}:BLOFfset:CUSTOMValue {baseline_offset_on_stop}")
        else: self.CheckWrite(f"OUTPut{channel.value}:BLOFfset:CUSTOMValue {minmax.value}")

    def GetCorrectionOffset(self, channel: Channel, minmax: GetValue):
        return self.CheckQuery(f"OUTPut{channel.value}:CROFfset? {minmax.value}")
    
    def SetCorrectionOffset(self, channel: Channel, correction_offset: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"OUTPut{channel.value}:CROFfset {correction_offset}")
        else: self.CheckWrite(f"OUTPut{channel.value}:CROFfset {minmax.value}")
    
    def GetChannelSkew(self, channel: Channel, minmax: GetValue):
        return self.CheckQuery(f"OUTPut{channel.value}:DELay? {minmax.value}")
    
    def SetChannelSkew(self, channel: Channel, delay: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"OUTPut{channel.value}:DELay {delay}")
        else: self.CheckWrite(f"OUTPut{channel.value}:DELay {minmax.value}")

    def GetValueOnStopStateChannel(self, channel: Channel):
        return self.CheckQuery(f"OUTPut{channel.value}:KEEPLast?")
    
    def SetValueOnStopStateChannel(self, channel: Channel, mode: KeepLastMode):
        self.CheckWrite(f"OUTPut{channel.value}:KEEPLast {mode.value}")

    def GetChannelPolarity(self, channel: Channel):
        return self.CheckQuery(f"OUTPut{channel.value}:POLarity?")
    
    def SetChannelPolarity(self, channel: Channel, polarity: Polarity):
        self.CheckWrite(f"OUTPut{channel.value}:POLarity {polarity.value}")

    def GetAmplitudeScale(self, channel: Channel, minmax: GetValue):
        return self.CheckQuery(f"OUTPut{channel.value}:SCALe? {minmax.value}")
    
    def SetAmplitudeScale(self, channel: Channel, scale: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"OUTPut{channel.value}:SCALe {scale}")
        else: self.CheckWrite(f"OUTPut{channel.value}:SCALe {minmax.value}")

    def GetStoppedValueChannel(self, channel: Channel, minmax: GetValue):
        return self.CheckQuery(f"OUTPut{channel.value}:CUSTOMValue? {minmax.value}")
    
    def SetStoppedValueChannel(self, channel: Channel, output_value_on_stop: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"OUTPut{channel.value}:CUSTOMValue {output_value_on_stop}")
        else: self.CheckWrite(f"OUTPut{channel.value}:CUSTOMValue {minmax.value}")

    def GetVocm(self, channel: Channel, minmax: GetValue):
        return self.CheckQuery(f"OUTPut{channel.value}:VOCM? {minmax.value}")
    
    def SetVocm(self, channel: Channel, vocm: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"OUTPut{channel.value}:VOCM {vocm}")
        else: self.CheckWrite(f"OUTPut{channel.value}:VOCM {minmax.value}")

    def GetValueOnStopStateDifferentialOut(self, channel: Channel):
        return self.CheckQuery(f"OUTPut{channel.value}:VOCM:KEEPLast?")
    
    def SetValueOnStopStateDifferentialOut(self, channel: Channel, mode: KeepLastMode):
        self.CheckWrite(f"OUTPut{channel.value}:VOCM:KEEPLast {mode.value}")
    
    def GetStoppedValueDifferentialOut(self, channel: Channel, minmax: GetValue):
        return self.CheckQuery(f"OUTPut{channel.value}:VOCM:CUSTOMValue? {minmax.value}")
    
    def SetStoppedValueDifferentialOut(self, channel: Channel, offset_on_stop: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"OUTPut{channel.value}:VOCM:CUSTOMValue {offset_on_stop}")
        else: self.CheckWrite(f"OUTPut{channel.value}:VOCM:CUSTOMValue {minmax.value}")

    def GetFineSkew(self, channel: Channel, minmax: GetValue):  #Only available for 4-channels models
        return self.CheckQuery(f"OUTPut{channel.value}:SKEWFine? {minmax.value}")
    
    def SetFineSkew(self, channel: Channel, skew: float, minmax: SetValue): #Only available for 4-channels models
        if minmax == SetValue.PRESENT: self.CheckWrite(f"OUTPut{channel.value}:SKEWFine {skew}")
        else: self.CheckWrite(f"OUTPut{channel.value}:SKEWFine {minmax.value}")

    def GetChannelOptimization(self, channel: Channel):
        return self.CheckQuery(f"OUTPut{channel.value}:OPTimization?")
    
    def SetChannelOptimization(self, channel: Channel, optimization: ChannelOptimization):
        self.CheckWrite(f"OUTPut{channel.value}:OPTimization {optimization.value}")

    def GetOvershootTuning(self, channel: Channel, minmax: GetValue):
        return self.CheckQuery(f"OUTPut{channel.value}:OVERShoot? {minmax.value}")
    
    def SetOvershootTuning(self, channel: Channel, overshoot: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"OUTPut{channel.value}:OVERShoot {overshoot}")
        else: self.CheckWrite(f"OUTPut{channel.value}:OVERShoot {minmax.value}")

    def GetFlatnessCompensation(self, channel: Channel):
        return self.CheckQuery(f"OUTPut{channel.value}:FLATComp?")
    
    def SetFlatnessCompensation(self, channel: Channel, state: State):
        self.CheckWrite(f"OUTPut{channel.value}:FLATComp {state.value}")


    #Parametric waveforms: gets and sets
    def GetAutoCalcOption(self, waveform_name: str):
        return self.CheckQuery(f"PW:ACOption? \"{waveform_name}\"")
    
    def SetAutoCalcOption(self, waveform_name: str, option: AutoCalcOption):
        self.CheckWrite(f"PW:ACOption \"{waveform_name}\",{option.value}")

    def GetOptimizedLengthForOption(self, waveform_name: str):
        return self.CheckQuery(f"PW:OPTFor? \"{waveform_name}\"")
    
    def SetOptimizedLengthForOption(self, waveform_name: str, optimization: OperatingMode):
        self.CheckWrite(f"PW:OPTFor \"{waveform_name}\", {optimization.value}")

    def GetParametricWaveformCommonCycles(self, waveform_name: str, selection: GetValue):
        return self.CheckQuery(f"PW:COMmon:CYCles? \"{waveform_name}\",{selection.value}")
    
    def SetParametricWaveformCommonCycles(self, waveform_name: str, cycles: int, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:COMmon:CYCles \"{waveform_name}\",{cycles}")
        else: self.CheckWrite(f"PW:COMmon:CYCles \"{waveform_name}\",{minmax.value}")

    def GetParametricWaveformCommonDuration(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:COMmon:DURation? \"{waveform_name}\", {minmax.value}")
    
    def SetParametricWaveformCommonDuration(self, waveform_name: str, duration: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:COMmon:DURation \"{waveform_name}\", {duration}")
        else: self.CheckWrite(f"PW:COMmon:DURation \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformCommonFrequency(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:COMmon:FREquency? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformCommonFrequency(self, waveform_name: str, frequency: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:COMmon:FREquency \"{waveform_name}\", {frequency}")
        else: self.CheckWrite(f"PW:COMmon:FREquency \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformCommonLength(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:COMmon:LENgth? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformCommonLength(self, waveform_name: str, length: int, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:COMmon:LENgth \"{waveform_name}\", {length}")
        else: self.CheckWrite(f"PW:COMmon:LENgth \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformCommonPeriod(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:COMmon:PERiod? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformCommonPeriod(self, waveform_name: str, period: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:COMmon:PERiod \"{waveform_name}\", {period}")
        else: self.CheckWrite(f"PW:COMmon:PERiod \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformCommonPhase(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:COMmon:PHAse? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformCommonPhase(self, waveform_name: str, phase: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:COMmon:PHAse \"{waveform_name}\", {phase}")
        else: self.CheckWrite(f"PW:COMmon:PHAse \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformCommonSamplingRate(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:COMmon:SRATe? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformCommonSamplingRate(self, waveform_name: str, sampling_rate: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:COMmon:SRATe \"{waveform_name}\", {sampling_rate}")
        else: self.CheckWrite(f"PW:COMmon:SRATe \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformExpMode(self, waveform_name: str):
        return self.CheckQuery(f"PW:EXP:MODe? \"{waveform_name}\"")
    
    def SetParametricWaveformExpMode(self, waveform_name: str, exp_mode: ExpMode):
        self.CheckWrite(f"PW:EXP:MODe \"{waveform_name}\", {exp_mode.value}")

    def GetParametricWaveformExpTimeConstant(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:EXP:TIMeconst? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformExpTimeConstant(self, waveform_name: str, time_constant: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:EXP:TIMeconst \"{waveform_name}\", {time_constant}")
        else: self.CheckWrite(f"PW:EXP:TIMeconst \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformPrbsType(self, waveform_name: str):
        return self.CheckQuery(f"PW:PRBs:TYPe? \"{waveform_name}\"")
    
    def SetParametricWaveformPrbsType(self, waveform_name: str, prbs_tipe: PRBSType):
        self.CheckWrite(f"PW:PRBs:TYPe \"{waveform_name}\", {prbs_tipe.value}")

    def GetParametricWaveformPrbsBitRate(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:PRBs:BITRate? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformPrbsBitRate(self, waveform_name: str, bit_rate: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:PRBs:BITRate \"{waveform_name}\", {bit_rate}")
        else: self.CheckWrite(f"PW:PRBs:BITRate \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformPulseDelay(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:PULse:PDElay? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformPulseDelay(self, waveform_name: str, delay: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:PULse:PDElay \"{waveform_name}\", {delay}")
        else: self.CheckWrite(f"PW:PULse:PDElay \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformPulseDutyCycle(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:PULse:DUTycycle? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformPulseDutyCycle(self, waveform_name: str, duty_cycle: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:PULse:DUTycycle \"{waveform_name}\", {duty_cycle}")
        else: self.CheckWrite(f"PW:PULse:DUTycycle \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformPulseFallTime(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:PULse:FALltime? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformPulseFallTime(self, waveform_name: str, fall_time: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:PULse:FALltime \"{waveform_name}\", {fall_time}")
        else: self.CheckWrite(f"PW:PULse:FALltime \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformPulseRiseTime(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:PULse:RISetime? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformPulseRiseTime(self, waveform_name: str, rise_time: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:PULse:RISetime \"{waveform_name}\", {rise_time}")
        else: self.CheckWrite(f"PW:PULse:RISetime \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformPulseWidth(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:PULse:PWIdth? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformPulseWidth(self, waveform_name: str, width: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:PULse:PWIdth \"{waveform_name}\", {width}")
        else: self.CheckWrite(f"PW:PULse:PWIdth \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformSincLobeWidth(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:SINC:LOBewidth? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformSincLobeWidth(self, waveform_name: str, width: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:SINC:LOBewidth \"{waveform_name}\", {width}")
        else: self.CheckWrite(f"PW:SINC:LOBewidth \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformSincLobePeakPosition(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:SINC:PEAkpos? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformSincLobePeakPosition(self, waveform_name: str, position: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:SINC:PEAkpos \"{waveform_name}\", {position}")
        else: self.CheckWrite(f"PW:SINC:PEAkpos \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformSquareFallTime(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:SQUare:FALltime? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformSquareFallTime(self, waveform_name: str, fall_time: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:SQUare:FALltime \"{waveform_name}\", {fall_time}")
        else: self.CheckWrite(f"PW:SQUare:FALltime \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformSquarePDelay(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:SQUare:PDElay? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformSquarePDelay(self, waveform_name: str, delay: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:SQUare:PDElay \"{waveform_name}\", {delay}")
        else: self.CheckWrite(f"PW:SQUare:PDElay \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformSquareRiseTime(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:SQUare:RISetime? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformSquareRiseTime(self, waveform_name: str, rise_time: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:SQUare:RISetime \"{waveform_name}\", {rise_time}")
        else: self.CheckWrite(f"PW:SQUare:RISetime \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformSweepStartFrequency(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:SWEep:STArtfreq? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformSweepStartFrequency(self, waveform_name: str, frequency: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:SWEep:STArtfreq \"{waveform_name}\", {frequency}")
        else: self.CheckWrite(f"PW:SWEep:STArtfreq \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformSweepStopFrequency(self, waveform_name: str, minmax: GetValue):
        return self.CheckQuery(f"PW:SWEep:STOpfreq? \"{waveform_name}\",{minmax.value}")
    
    def SetParametricWaveformSweepStopFrequency(self, waveform_name: str, frequency: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:SWEep:STOpfreq \"{waveform_name}\", {frequency}")
        else: self.CheckWrite(f"PW:SWEep:STOpfreq \"{waveform_name}\", {minmax.value}")

    def GetParametricWaveformSweepMode(self, waveform_name: str):
        return self.CheckQuery(f"PW:SWEep:MODe? \"{waveform_name}\"")
    
    def SetParametricWaveformSweepMode(self, waveform_name: str, mode: SweepMode):
        self.CheckWrite(f"PW:SWEep:MODe \"{waveform_name}\", {mode.value}")

    def GetParametricWaveformType(self, waveform_name: str):
        return self.CheckQuery(f"PW:TYPe? \"{waveform_name}\"")
    
    def SetParametricWaveformType(self, waveform_name: str, wave_type: WaveType):
        self.CheckWrite(f"PW:TYPe \"{waveform_name}\", {wave_type.value}")

    def GetWrapAroundState(self, waveform_name: str):
        return self.CheckQuery(f"PW:COMmon:WRAPAround? \"{waveform_name}\"")
    
    def SetWrapAroundState(self, waveform_name: str, state: State):
        self.CheckWrite(f"PW:COMmon:WRAPAround \"{waveform_name}\", {state.value}")

    def GetMultitoneFrequency(self, waveform_name: str, tone: Tone, minmax: GetValue):
        return self.CheckQuery(f"PW:MULtit:TONe{tone}:FREquency? \"{waveform_name}\", {minmax.value}")
    
    def GetToneAmplitude(self, waveform_name: str, tone: Tone, minmax: GetValue):
        return self.CheckQuery(f"PW:MULtit:TONe{tone}:AMPlitude? \"{waveform_name}\", {minmax.value}")
    
    def SetToneAmplitude(self, waveform_name: str, tone: Tone, amplitude: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:MULtit:TONe{tone}:AMPlitude \"{waveform_name}\",{amplitude}")
        else: self.CheckWrite(f"PW:MULtit:TONe{tone}:AMPlitude \"{waveform_name}\",{minmax.value}")
    
    def GetTonePhase(self, waveform_name: str, tone: Tone, minmax: GetValue):
        return self.CheckQuery(f"PW:MULtit:TONe{tone}:PHAse? \"{waveform_name}\", {minmax.value}")
    
    def SetTonePhase(self, waveform_name: str, tone: Tone, amplitude: float, minmax: SetValue):
        if minmax == SetValue.PRESENT: self.CheckWrite(f"PW:MULtit:TONe{tone}:PHAse \"{waveform_name}\",{amplitude}")
        else: self.CheckWrite(f"PW:MULtit:TONe{tone}:PHAse \"{waveform_name}\",{minmax.value}")
    
    def GetTonesNumber(self, waveform_name: str):
        return self.CheckQuery(f"PW:MULtit:NUM? \"{waveform_name}\"")
    
    def AddNewToneParametricWave(self, waveform_name: str, frequency_selection: SetValue, amplitude_selection: SetValue, phase_selection: SetValue,
                                 frequency: float, amplitude: float, phase: float):
        command: str = f"PW:MULtit:ADD \"{waveform_name}\","
        if frequency_selection == SetValue.PRESENT: command = command + str(frequency) + ","
        else: command = command + frequency_selection.value
        if amplitude_selection == SetValue.PRESENT: command = command + str(amplitude) + ","
        else: command = command + amplitude_selection.value
        if phase_selection == SetValue.PRESENT: command = command + str(phase)
        else: command = command + phase_selection.value
        self.CheckWrite(command)
        
    def DeleteTone(self, waveform_name: str, tone_selection: SpecificOrAll, tone: Tone):
        command: str = f"PW:MULtit:DELete \"{waveform_name}\", "
        if tone_selection == SpecificOrAll.Specific: command = command + str(tone)
        else: command = command + tone_selection.value
        self.CheckWrite(command)

    def CreateParametricWaveform(self, waveform_name: str, attribute: WaveformAttribute, description: str):
        self.CheckWrite(f"PW:CREATE \"{waveform_name}\", {attribute.value}, \"{description}\"")

    def DeleteParametricWaveform(self, waveform_name: str, selection: SpecificOrAll):
        if selection == SpecificOrAll.All: self.CheckWrite(f"PW:DELETE {selection.value}")
        else: self.CheckWrite(f"PW:DELETE \"{waveform_name}\"")
    
    def DuplicateParametricWaveform(self, target_name: str, newwave_name: str):
        self.CheckWrite(f"PW:DUPLICATE \"{target_name}\", \"{newwave_name}\"")

    def RenameParametricWaveform(self, target_name: str, new_wavename: str):
        self.CheckWrite(f"PW:RENAME \"{target_name}\", \"{new_wavename}\"")

    #General
    def GetBurstCount(self, minmax: GetValue):
        return self.CheckQuery(f"AWGControl:BURST? {minmax.value}")
    
    def SetBurstCount(self, count: int, selection: BurstSelection):
        if selection != BurstSelection.NumberCycles: self.CheckWrite(f"AWGControl:BURST {selection.value}")
        else: self.CheckWrite(f"AWGControl:BURST {count}")
    
    def GetJumpMode(self):
        return self.CheckQuery(f"AWGControl:JUMPMode?")
    
    def SetJumpMode(self, mode: JumpMode):
        self.CheckWrite(f"AWGControl:JUMPMode {mode.value}")
    
    def GetRunMode(self):
        return self.CheckQuery(f"AWGControl:RMODe?")
    
    def SetRunMode(self, mode: RunMode):
        self.CheckWrite(f"AWGControl:RMODe {mode.value}")
    
    def GetWaitTriggerState(self):
        return self.CheckQuery(f"AWGControl:WAITstate?")
    
    def SetWaitTriggerState(self, state: WaitTriggerState):
        self.CheckWrite(f"AWGControl:WAITstate {state.value}")

    def GetOperatingMode(self):
        return self.CheckQuery("AWGControl:OPERATINGMode?")
    
    def SetOperatingMode(self, operating_mode: OperatingMode):
        self.CheckWrite(f"AWGControl:OPERATINGMode {operating_mode.value}")

    #Sequencer parameters
    def GetChannelDecreasingStrategy(self):
        return self.CheckQuery("AWGControl:DECreasing?")
    
    def SetChannelDecreasingStrategy(self, strategy: DecreasingStrategy):
        self.CheckWrite(f"AWGControl:DECreasing {strategy.value}")

    def GetChannelIncreasingStrategy(self):
        return self.CheckQuery("AWGControl:INCreasing?")
    
    def SetChannelIncreasingStrategy(self, strategy: IncreasingStrategy):
        self.CheckWrite(f"AWGControl:INCreasing {strategy.value}")

    def GetEntryGoToltem(self, element: int, minmax: GetValue):
        return self.CheckQuery(f"SEQuence:ELEM{element}:GOTOEntry? {minmax.value}")

    def SetEntryGoToltem(self, element: int, entry: int, option: SetValue):
        if option != SetValue.PRESENT: self.CheckWrite(f"SEQuence:ELEM{element}:GOTOEntry {option.value}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:GOTOEntry {entry}")

    def GetChannelDelay(self, element: int, channel: Channel, minmax: GetValue):
        return self.CheckQuery(f"SEQuence:ELEM{element}:DELAy{channel.value}? {minmax.value}")

    def SetChannelDelay(self, element: int, channel: Channel, delay: float, minmax: SetValue):
        if minmax != SetValue.PRESENT: self.CheckWrite(f"SEQuence:ELEM{element}:DELAy {channel.value} {minmax.value}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:DELAy{channel.value} {delay}")

    def GetChannelSubLength(self, element: int, channel: ChannelEntry, minmax: GetValue):
        if channel == ChannelEntry.ProgrammedMarker: return self.CheckQuery(f"SEQuence:ELEM{element}:SUBLength{str(int(self.GetChannelsOutputNumber()) + 1)}? {minmax.value} ")
        elif channel == ChannelEntry.Digital: return self.CheckQuery(f"SEQuence:ELEM{element}:SUBLength{str(int(self.GetChannelsOutputNumber()) + 2)}? {minmax.value} ")
        else: return self.CheckQuery(f"SEQuence:ELEM{element}:SUBLength{channel.value}? {minmax.value} ")

    def SetChannelSubLength(self, element: int, channel: ChannelEntry, sub_length: int, minmax: SetValue):
        sub_length_str = str(sub_length)
        if minmax == SetValue.DEFAULT: sub_length_str = "DEFault"
        if channel == ChannelEntry.ProgrammedMarker: self.CheckWrite(f"SEQuence:ELEM{element}:SUBLength{str(int(self.GetChannelsOutputNumber()) + 1)} {sub_length_str} ")
        elif channel == ChannelEntry.Digital: self.CheckWrite(f"SEQuence:ELEM{element}:SUBLength{str(int(self.GetChannelsOutputNumber()) + 2)} {sub_length_str} ")
        else: return self.CheckWrite(f"SEQuence:ELEM{element}:SUBLength{channel.value} {sub_length_str} ")

    def GetEntryGoToMode(self, element: int):
        return self.CheckQuery(f"SEQuence:ELEM{element}:GOTOMode?")

    def SetEntryGoToMode(self, element: int, mode: Mode):
        self.CheckWrite(f"SEQuence:ELEM{element}:GOTOMode {mode.value}")

    def GetEntryJumpEvent(self, element: int):
        return self.CheckQuery(f"SEQuence:ELEM{element}:JUMPEvent?")
    
    def SetEntryJumpEvent(self, element: int, jump_event: JumpEvent):
        self.CheckWrite(f"SEQuence:ELEM{element}:JUMPEvent {jump_event.value}")

    def GetEntryJumpToltem(self, element: int, minmax: GetValue):
        return self.CheckQuery(f"SEQuence:ELEM{element}:JUMPTOEntry? {minmax.value}")
    
    def SetEntryJumpToltem(self, element: int, entry: int, option: SetValue):
        if option != SetValue.PRESENT: self.CheckWrite(f"SEQuence:ELEM{element}:JUMPTOEntry {option.value}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:GOTOEntry {entry}")

    def GetEntryJumpToMode(self, element: int):
        return self.CheckQuery(f"SEQuence:ELEM{element}:JUMPTOMode?")

    def SetEntryJumpToMode(self, element: int, mode: Mode):
        self.CheckWrite(f"SEQuence:ELEM{element}:JUMPTOMode {mode.value}")

    def GetEntryLength(self, element: int, minmax: GetValue):
        return self.CheckQuery(f"SEQuence:ELEM{element}:LENGth? {minmax.value}")
    
    def SetEntryLength(self, element: int, length: int, option: SetValue):
        if option != SetValue.PRESENT: self.CheckWrite(f"SEQuence:ELEM{element}:LENGth {option.value}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:LENGth {length}")

    def GetEntryPatternCode(self, element: int, minmax: GetValue):
        return self.CheckQuery(f"SEQuence:ELEM{element}:PATTERN? {minmax.value}")
    
    def SetEntryPatternCode(self, element: int, pattern_code: int, option: SetValue):
        if option != SetValue.PRESENT: self.CheckWrite(f"SEQuence:ELEM{element}:PATTERN {option.value}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:PATTERN {pattern_code}")

    def GetEntryPatternJumpToItem(self, element: int, minmax: GetValue):
        return self.CheckQuery(f"SEQuence:ELEM{element}:PATTERNJUMPTOEntry? {minmax.value}")
    
    def SetEntryPatternJumpToItem(self, element: int, entry_item: int, option: SetValue):
        if option != SetValue.PRESENT: self.CheckWrite(f"SEQuence:ELEM{element}:PATTERNJUMPTOEntry {option.value}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:PATTERNJUMPTOEntry {entry_item}")

    def GetEntryPatternMode(self, element: int):
        return self.CheckQuery(f"SEQuence:ELEM{element}:PATTERNJUMPTOMode?")

    def SetEntryPatternMode(self, element: int, mode: Mode):
        self.CheckWrite(f"SEQuence:ELEM{element}:PATTERNJUMPTOMode {mode.value}")

    def GetEntryRepetitions(self, element: int, minmax: GetValue):
        return self.CheckQuery(f"SEQuence:ELEM{element}:LOOP:COUNt? {minmax.value}")
    
    def SetEntryRepetitions(self, element: int, entry_repetitions: int, option: SetValue2):
        if option != SetValue2.PRESENT: self.CheckWrite(f"SEQuence:ELEM{element}:LOOP:COUNt {option.value}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:LOOP:COUNt {entry_repetitions}")

    def GetEntryWaitEvent(self, element: int):
        return self.CheckQuery(f"SEQuence:ELEM{element}:WAITEvent?")

    def SetEntryWaitEvent(self, element: int, event: JumpEvent):
        self.CheckWrite(f"SEQuence:ELEM{element}:WAITEvent {event.value}")

    def GetChannelAmplitude(self, channel: Channel, element: int, minmax: GetValue):
        return self.CheckQuery(f"SEQuence:ELEM{element}:AMPlitude{channel.value}? {minmax.value}")
    
    def SetChannelAmplitude(self, element: int, channel: Channel, amplitude: float, option: SetValue):
        if option != SetValue.PRESENT: self.CheckWrite(f"SEQuence:ELEM{element}:AMPlitude{channel.value} {option.value}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:AMPlitude{channel.value} {amplitude}")

    def GetChannelWaveform(self, element: int, channel: Channel):
        return self.CheckQuery(f"SEQuence:ELEM{element}:WAVeform{channel.value}?")

    def SetChannelWaveform(self, element: int, channel: ChannelEntry, waveform_name: str, output_format: OutputFormat):
        if output_format == OutputFormat.Take_last: waveform_name = "TAKELast"
        else: waveform_name = f"\"{waveform_name}\""
        if channel == ChannelEntry.ProgrammedMarker:
            self.SetMarkerMode(Marker.Marker1, MarkerMode.Custom_Pattern)
            if self.GetChannelsOutputNumber() == "4": self.SetMarkerMode(Marker.Marker2, MarkerMode.Custom_Pattern)
            self.CheckWrite(f"SEQuence:ELEM{element}:WAVeform{self.number_of_channels + 1} {waveform_name}")
        elif channel == ChannelEntry.Digital: self.CheckWrite(f"SEQuence:ELEM{element}:WAVeform{self.number_of_channels + 2} {waveform_name}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:WAVeform{channel.value} {waveform_name}")

    def GetChannelOffset(self, channel: Channel, element: int, minmax: GetValue):
        return self.CheckQuery(f"SEQuence:ELEM{element}:OFFset{channel.value}? {minmax.value}")
    
    def SetChannelOffset(self, element: int, channel: Channel, offset: float, option: SetValue):
        if option != SetValue.PRESENT: self.CheckWrite(f"SEQuence:ELEM{element}:OFFset{channel.value} {option.value}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:OFFset{channel.value} {offset}")

    def GetChannelVoltageHigh(self, channel: Channel, element: int, minmax: GetValue):
        return self.CheckQuery(f"SEQuence:ELEM{element}:VOLTage:HIGH{channel.value}? {minmax.value}")
    
    def SetChannelVoltageHigh(self, element: int, channel: Channel, vhigh: float, option: SetValue):
        if option != SetValue.PRESENT: self.CheckWrite(f"SEQuence:ELEM{element}:VOLTage:HIGH{channel.value} {option.value}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:VOLTage:HIGH{channel.value} {vhigh}")

    def GetChannelVoltageLow(self, channel: Channel, element: int, minmax: GetValue):
        return self.CheckQuery(f"SEQuence:ELEM{element}:VOLTage:LOW{channel.value}? {minmax.value}")
    
    def SetChannelVoltageLow(self, element: int, channel: Channel, vlow: float, option: SetValue):
        if option != SetValue.PRESENT: self.CheckWrite(f"SEQuence:ELEM{element}:VOLTage:LOW{channel.value} {option.value}")
        else: self.CheckWrite(f"SEQuence:ELEM{element}:VOLTage:LOW{channel.value} {vlow}")

    def GetSequencerLength(self):
        return self.CheckQuery("SEQuence:LENGth?")
    
    def SetSequencerLength(self, length: int, option: SetValue):
        if option != SetValue.PRESENT: self.CheckWrite(f"SEQuence:LENGth {option.value}")
        else: self.CheckWrite(f"SEQuence:LENGth {length}")

    def CreateNewSequencer(self):
        self.CheckWrite("SEQuence:NEW")

    #Sequencer settings
    def GetEntryLengthStrategy(self):
        return self.CheckQuery("AWGControl:LENGth:MODE?")
    
    def SetEntryLengthStrategy(self, strategy: SequencerLengthStrategy):
        self.CheckWrite(f"AWGControl:LENGth:MODE {strategy.value}")

    def GetDefaultDecreasingStrategy(self):
        return self.CheckQuery("AWGControl:DECreasing?")
    
    def SetDefaultDecreasingStrategy(self, strategy: DecreasingStrategy):
        self.CheckWrite(f"AWGControl:DECreasing {strategy.value}")

    def GetDefaultIncreasingStrategy(self):
        return self.CheckQuery("AWGControl:INCreasing?")
    
    def SetDefaultIncreasingStrategy(self, strategy: IncreasingStrategy):
        self.CheckWrite(f"AWGControl:INCreasing {strategy.value}")

    #Timing
    def GetClockSource(self):
        return self.CheckQuery("ROSCillator:SOURce?")
    
    def SetClockSource(self, source: ClockSource):
        self.CheckWrite(f"ROSCillator:SOURce {source.value}")

    def GetExternalClockDivisor(self):
        return self.CheckQuery("EXTSampclock:DIVisor?")
    
    def SetExternalClockDivisor(self, divisor: ExtClkDivisor):
        self.CheckWrite(f"EXTSampclock:DIVisor {divisor.value}")

    def GetExternalClockInFrequency(self):
        return self.CheckQuery("EXTSampclock:VALue?")
    
    def GetReferenceClockFrequency(self, minmax: GetValue):
        return self.CheckQuery(f"ROSCillator? {minmax.value}")
    
    def SetReferenceClockFrequency(self, frequency: float, minmax: SetValue):
        if minmax != SetValue.PRESENT: self.CheckWrite(f"ROSCillator {minmax.value}")
        else: self.CheckWrite(f"ROSCillator {frequency}")

    def GetSamplingClockFrequency(self, minmax: GetValue):
        return self.CheckQuery(f"AWGControl:SRATe? {minmax.value}")
    
    def SetSamplingClockFrequency(self, frequency: float, minmax: SetValue):
        if minmax != SetValue.PRESENT: self.CheckWrite(f"AWGControl:SRATe {minmax.value}")
        else: self.CheckWrite(f"AWGControl:SRATe {frequency}")

    def GetSyncClockOutFrequency(self):
        return self.CheckQuery(f"SYNCclockout:VALue?")
    
    def GetSyncClockOutSelector(self):
        return self.CheckQuery(f"SYNCclockout:SELector?")
    
    def SetSyncClockOutSelector(self, selector: SyncClockOutSelector):
        self.CheckWrite(f"SYNCclockout:SELector {selector.value}")

    def GetSyncClockOutState(self):
        return self.CheckQuery(f"SYNCclockout:STATe?")
    
    def SetSyncClockOutState(self, state: State):
        self.CheckWrite(f"SYNCclockout:STATe {state.value}")

    def GetLowJitterTriggerState(self):
        return self.CheckQuery(f"LOWJitter:STATe?")
    
    def SetLowJitterTriggerState(self, state: State):
        self.CheckWrite(f"LOWJitter:STATe {state.value}")

    #Trigger in
    def GetTriggerDelayAdjust(self, trigger: TriggerIn, minmax: GetValue):
        return self.CheckQuery(f"TRIGger:DELAYadjust{trigger.value}? {minmax.value}")
    
    def SetTriggerDelayAdjust(self, trigger: TriggerIn, delay: float, minmax: SetValue):
        if minmax != SetValue.PRESENT: self.CheckWrite(f"TRIGger:DELAYadjust{trigger.value} {minmax.value}")
        else: self.CheckWrite(f"TRIGger:DELAYadjust{trigger.value} {delay}")

    def GetTriggerImpedance(self, trigger: TriggerIn):
        return self.CheckQuery(f"TRIGger{trigger.value}:IMPedance?")
    
    def SetTriggerImpedance(self, trigger: TriggerIn, impedance: Impedance):
        self.CheckWrite(f"TRIGger{trigger.value}:IMPedance {impedance.value}")

    def GetTriggerInterval(self, minmax: GetValue):
        return self.CheckQuery(f"TRIGger:TIMer? {minmax.value}")
    
    def SetTriggerInterval(self, interval: float, minmax: SetValue):
        if minmax != SetValue.PRESENT: self.CheckWrite(f"TRIGger:TIMer {minmax.value}")
        else: self.CheckWrite(f"TRIGger:TIMer {interval}")

    def GetTriggerThreshold(self, trigger: TriggerIn, minmax: GetValue):
        return self.CheckQuery(f"TRIGger{trigger.value}:LEVel? {minmax.value}")
    
    def SetTriggerThreshold(self, trigger: TriggerIn, threshold: float, minmax: SetValue):
        if minmax != SetValue.PRESENT: self.CheckWrite(f"TRIGger{trigger.value}:LEVel {minmax.value}")
        else: self.CheckWrite(f"TRIGger{trigger.value}:LEVel {threshold}")

    def GetTriggerEdge(self, trigger: TriggerIn):
        return self.CheckQuery(f"TRIGger{trigger.value}:SLOPe?")
    
    def SetTriggerEdge(self, trigger: TriggerIn, slope: Slope):
        self.CheckWrite(f"TRIGger{trigger.value}:SLOPe {slope.value}")

    def GetTriggerSource(self):
        return self.CheckQuery("TRIGger:SOURce?")
    
    def SetTriggerSource(self, source: TriggerInSource):
        self.CheckWrite(f"TRIGger:SOURce {source.value}")
 
    def GetTriggerTimingMode(self, trigger: TriggerIn):
        return self.CheckQuery(f"TRIGger:FASTasync{trigger.value}?")
    
    def SetTriggerTimingMode(self, trigger: TriggerIn, mode: TriggerTiming):
        self.CheckWrite(f"TRIGger:FASTasync{trigger.value} {mode.value}")

    #Waveforms list
    def DeleteWaveformsList(self, waveform_name: str, option: SpecificOrAll):
        if option != SpecificOrAll.All: self.CheckWrite(f"WLISt:WAVeform:DELete \"{waveform_name}\"")
        else: self.CheckWrite(f"WLISt:WAVeform:DELete ALL")

    def ExportWaveformInFile(self, drive: str, directory: str, waveform_name: str, archive_name: str):
        """"directory: relative path from the current folder
            waveform: must not be predefined
            archive_name: must be a .zip archive"""
        self.CheckWrite(f"MMEMory:CDIRectory \"{directory}\"")
        self.CheckWrite(f"MMEMory:EXPort \"{waveform_name}\", \"{archive_name}\"")

    def GetWaveformLength(self, waveform_name: str, option: GetValue):
        if option == GetValue.PRESENT: return self.CheckQuery(f"WLISt:WAVeform:LENGth? \"{waveform_name}\"")
        elif option == GetValue.MINIMUM: return self.CheckQuery(f"WLISt:WAVeform:LMINimum?")
        else: return self.CheckQuery(f"WLISt:WAVeform:LMAXimum?")

    def GetWaveformName(self, list_index: int):
        return self.CheckQuery(f"WLISt:NAME? {list_index}")
    
    def GetWaveformParametric(self, waveform_name: str):
        return self.CheckQuery(f"WLISt:WAVeform:PARametric? \"{waveform_name}\"")
    
    def GetWaveformPredefined(self, waveform_name: str):
        return self.CheckQuery(f"WLISt:WAVeform:PREDefined? \"{waveform_name}\"")
    
    def GetWaveformsList(self):
        return self.CheckQuery("WLISt:LIST?")
    
    def GetWaveformsListSize(self):
        return self.CheckQuery("WLISt:SIZE?")
    
    def GetWaveformType(self, waveform_name: str):
        return self.CheckQuery(f"WLISt:WAVeform:TYPE? \"{waveform_name}\"")

    def ImportFileInWaveformList(self, waveform_name: str, file_path: str, waveform_type: WaveformType):
        """Import a waveform from a folder in the instrument file system into the waveforms list.
            ARGS: waveform_name: Name of the waveform that will be added to the waveforms list
                  file_path: absolute path or relative path of the file"""
        self.CheckWrite(f"WLISt:WAVeform:IMPort \"{waveform_name}\", \"{file_path}\", {waveform_type.value}")

    #EXTERNAL PATTERN JUMPS
    def GetEPJEntryEnable(self, pattern: int):
        return self.CheckQuery(f"AWGControl:DJump:EXTernal:ENABle? {pattern}")

    def SetEPJEntryEnable(self, pattern: int, state: State):
        self.CheckWrite(f"AWGControl:DJump:EXTernal:ENABle {pattern}, {state.value}")

    def GetEPJOptionEnable(self):
        return self.CheckQuery(f"AWGControl:DJump:ENABle?")
    
    def SetEPJOptionEnable(self, state: State):
        self.CheckWrite(f"AWGControl:DJump:ENABle {state.value}")

    def GetJumpToEntry(self, pattern: int):
        return self.CheckQuery(f"AWGControl:DJump:EXTernal:JUMPTOEntry? {pattern}")
    
    def SetJumpToEntry(self, pattern: int, entry: int):
        self.CheckWrite(f"AWGControl:DJump:EXTernal:JUMPTOEntry {pattern}, {entry}")

    def GetStrobePolarity(self):
        return self.CheckQuery(f"AWGControl:DJump:POLarity?")
    
    def SetStrobePolarity(self, polarity: Polarity):
        self.CheckWrite(f"AWGControl:DJump:POLarity {polarity.value}")


    #MULTIINSTRUMENT
    def Capture(self):
        self.CheckWrite(f"MIM:CAPTure")
    
    def Release(self):
        self.CheckWrite(f"MIM:RELease")

    def IsSlave(self):
        return self.CheckQuery(f"MIM:SLAve?")

    def GetMultiInstrumentID(self):
        return self.CheckQuery("MIM:ID?")
    
    def IsForwardPresent(self):
        return self.CheckQuery("MIM:FORWard?")
    
    def IsCaptured(self):
        return self.CheckQuery("MIM:CAPTured?")

    def GetCapturedDevices(self):
        return self.CheckQuery("MIM:NUMber?")


    #UTILITY
    #Beeper
    def GetSystemBeeperState(self):
        return self.CheckQuery(f"SYSTem:BEEPer:STATe?")
    
    def SetSystemBeeperState(self, state: State):
        self.CheckWrite(f"SYSTem:BEEPer:STATe {state.value}")
    
    def SystemBeeper(self):
        self.CheckWrite("SYSTem:BEEPer")

    #Memory device settings
    def AvailableMemories(self):
        return self.CheckQuery(f"MEMory:NSTates?")
    
    def DeleteMemory(self, memory: Memory, configuration_name: str):
        if memory == Memory.Memory4: self.CheckWrite(f"MEMory:STATe:DELete {configuration_name}")
        else: self.CheckWrite(f"MEMory:STATe:DELete {memory.value}")

    def ExportConfigurationToFile(self, absolute_path: str):
        self.CheckWrite(f"MMEMory:SAVE:SETup {absolute_path}")

    def GetMemoryStateCatalog(self):
        self.CheckQuery(f"MEMory:STATe:CATalog?")

    def ImportConfigurationFromFile(self, file: str):
        self.CheckWrite(f"MMEMory:OPEN:SETup \"{file}\"")

    def LoadConfigurationFromSetupMemory(self, memory: Memory, configuration_name: str):
        if memory == Memory.Configuration: self.CheckWrite(f"AWGControl:SREStore \"{configuration_name}\"")
        else: self.CheckWrite(f"*RCL {memory.value}")

    def MemoryStateValid(self, memory: Memory, configuration_name: str):
        if memory == Memory.Configuration: return self.CheckQuery(f"MEMory:STATe:VALid? \"{configuration_name}\"")
        else: return self.CheckQuery(f"MEMory:STATe:VALid? {memory.value}")

    def SaveConfigurationToSetupMemory(self, memory: Memory, configuration_name: str):
        if memory == Memory.Configuration: self.CheckWrite(f"AWGControl:SSAVe \"{configuration_name}\"")
        else: self.CheckWrite(f"*SAV {memory.value}")


    #SERVICE MESSAGE
    def GetServiceMessage(self):
        return self.CheckQuery("DISPlay:TEXT? ")
    
    def SetServiceMessage(self, message: str):
        self.CheckWrite(f"DISPlay:TEXT \"{message}\"")

    def ServiceMessageClear(self):
        self.CheckWrite("DISPlay:TEXT:CLEar")


    #TRANSFER FILE
    def ChangeCurrentDirectory(self, directory: str):
        self.CheckWrite(f"MMEMory:CDIRectory \"{directory}\"")

    def GetCurrentDirectory(self):
        return self.CheckQuery(f"MMEMory:CDIRectory?")

    def DeleteFile(self, file: str):
        self.CheckWrite(f"MMEMory:DELete \"{file}\"")

    def TransferFile(self, source_file: str, source_file_new_name: str, destination_file_folder_realtive_path="", chunk_size=2000000):
        """Transfer a file from the PC to mass storage memory of the instrument.
            Args: source_file: relative or absolute path of the file in the PC
                  source_file_new_name: name of the new file which will be created in the instrument file system
                  destination_file_folder: unless you changed it, must be the default folder of the instrument (if you are unsure, you can use the GetDefaultDriveCFolder command)
                  chunk_size: see True Arb Programming Manual"""
        with open(source_file, 'r') as file:
            read_file = str(file.read())
        file_size = sys.getsizeof(read_file)
        size_remainder = file_size % chunk_size
        size_quotient = file_size // chunk_size
        read_file_length = len(read_file)
        if size_quotient == 0: self.CheckWrite(f"MMEMory:DATA \"{destination_file_folder_realtive_path}\\{source_file_new_name}\",0,#{len(str(read_file_length))}{len(read_file)}{read_file}")
        else:
            for i in range(size_quotient): self.CheckWrite(f"MMEMory:DATA \"{destination_file_folder_realtive_path}\\{source_file_new_name}\",{i*chunk_size},#{len(str(chunk_size))}{chunk_size}{read_file[i*chunk_size, i*chunk_size+chunk_size]}")
            if size_remainder != 0: self.CheckWrite(f"MMEMory:DATA \"{destination_file_folder_realtive_path}\\{source_file_new_name}\",{size_quotient*chunk_size},#{len(str(size_remainder))}{size_remainder}{read_file[chunk_size*size_quotient:]}")
    
    def APPSwitch(self, app: App):
        self.instrument.write(f"AWGControl:APPSwitch {app.value}")

    def Calibration(self):      #Increase the timeout to at least 5 minutes
        self.AWGStop()
        return self.CheckQuery("CALibration?")
    
    def ChangeFormat(self, format: Format):
        self.CheckWrite(f"DISPlay:UNIT:VOLT {format.value}")

    def Date(self):
        return self.CheckQuery("SYSTem:DATE?")
    
    def Diagnostic(self):
        self.AWGStop()
        return self.CheckQuery("DIAGnostic?")
    
    def GetChannelsOutputNumber(self):
        return self.CheckQuery("AWGControl:CONFigure:CNUMber?")

    def GetDefaultDriveCFolder(self):
        self.CheckWrite("MMEMory:MSIS \"C:\"")
        self.CheckWrite("MMEMory:CDIRectory")
        return self.CheckQuery("MMEMory:CDIRectory?")
    
    def GetDigitalOutputNumber(self):
        return self.CheckQuery("AWGControl:CONFigure:DNUMber?")
    
    def Reset(self):
        self.CheckWrite("*RST")

    def SetSystemKLOCk(self, lock: bool):
        self.CheckWrite(f"SYSTem:KLOCk {lock}")

    def SystemSecurity(self):
        self.CheckWrite("SYSTem:SECurity:IMMediate")

    def Time(self):
        return self.CheckQuery("SYSTem:TIME?")
    
    def TryDeleteWaveform(self, waveform_name: str):
        if waveform_name in self.GetWaveformsList() and self.GetWaveformPredefined(waveform_name) == 0:
            self.DeleteWaveformsList(waveform_name, SpecificOrAll.Specific)
            return 1
        else: return 0


    #CONFIGURE
    def ConfigureChannelSettings(self, channel: Channel, amplitude_scale: float, skew: float, fine_skew: float, correction_offset: float, Vocm: float,
                                 mode: KeepLastMode, polarity: Polarity, offset_on_stop: float, baseline_offset: float, optimization: ChannelOptimization,
                                 overshoot: float, flatness_compensation: State, channel_value_on_stop_state: KeepLastMode, output_value_on_stop: float):
        try:
            self.SetAmplitudeScale(channel, amplitude_scale, SetValue.PRESENT)
            self.SetChannelSkew(channel, skew, SetValue.PRESENT)
            if self.GetChannelsOutputNumber() == "4": self.SetFineSkew(channel, fine_skew, SetValue.PRESENT)
            self.SetCorrectionOffset(channel, correction_offset, SetValue.PRESENT)
            ID = self.CheckQuery("*IDN?")
            if "2D" in ID or "4D" in ID:
                self.SetVocm(channel, Vocm, SetValue.PRESENT)
                self.SetValueOnStopStateDifferentialOut(channel, mode)
                self.SetStoppedValueDifferentialOut(channel, offset_on_stop, SetValue.PRESENT)
            else:
                self.SetBaselineOffset(channel, baseline_offset, SetValue.PRESENT)
                self.SetValueOnStopStateSingleEnded(channel, mode)
                self.SetStoppedValueSingleEndedOut(channel, offset_on_stop, SetValue.PRESENT)
            self.SetChannelPolarity(channel, polarity)
            self.SetChannelOptimization(channel, optimization)
            self.SetOvershootTuning(channel, overshoot, SetValue.PRESENT)
            self.SetFlatnessCompensation(channel, flatness_compensation)
            self.SetValueOnStopStateChannel(channel, channel_value_on_stop_state)
            self.SetStoppedValueChannel(channel, output_value_on_stop, SetValue.PRESENT)
        except Exception as e: raise Exception(e)

    def ConfigureDigitalChannels(self, nchannels: ChannelsNumber, pod: Pod, dtt_voltage: float, dtt_voltage_option: SetValue, CML_level: CMLVoltageLevel,
                                 equalization_factor: float, equalization_factor_option: SetValue, skew: float, skew_option: SetValue):
        try:
            possible_numbers_of_digital_channels = ["8 Digitals", "16 Digitals", "24 Digitals", "32 Digitals"]
            license = self.CheckQuery("*OPT?")
            for i in possible_numbers_of_digital_channels:
                if i in license:
                    self.SetDigitalChannelsNumber(nchannels)
                    self.SetDigitalPodDTTLLevel(pod, dtt_voltage, dtt_voltage_option)
                    self.SetDigitalPodCMLVoltageLevel(pod, CML_level)
                    self.SetDigitalPodCMLEqualizationFactor(pod, equalization_factor, equalization_factor_option)
                    self.SetDigitalPodSkew(pod, skew, skew_option)
                    break
        except Exception as e: raise Exception(e)

    def ConfigureExternalForceJumps(self, enable: State, polarity: Polarity, pattern: int, enable_pattern: State, entry: int):
        try:
            self.SetEPJOptionEnable(enable)
            self.SetStrobePolarity(polarity)
            if enable == State.ON:
                self.SetEPJEntryEnable(pattern, enable_pattern)
                self.SetJumpToEntry(pattern, entry)
        except Exception as e: raise Exception(e)

    def ConfigureGeneralSettings(self, operating_mode: OperatingMode, sample_increasing_strategy: IncreasingStrategy, sample_decreasing_startegy: DecreasingStrategy,
                                 run_mode: RunMode, wait_trigger_on: WaitTriggerState, burst_count: int, burst_selection: BurstSelection, jump_mode: JumpMode):
        try:
            self.SetRunMode(run_mode)
            self.SetDefaultIncreasingStrategy(sample_increasing_strategy)
            self.SetDefaultDecreasingStrategy(sample_decreasing_startegy)
            ID = self.CheckQuery("*IDN?")
            if not ("AWG7102" in ID or "AWG7104" in ID): self.SetOperatingMode(operating_mode)
            self.SetWaitTriggerState(wait_trigger_on)
            self.SetBurstCount(burst_count, burst_selection)
            self.SetJumpMode(jump_mode)
        except Exception as e: raise Exception(e)

    def ConfigureMarkerOut(self, marker: Marker, mode: MarkerMode, vhigh: float, option_vhigh: SetValue, vlow: float, option_vlow: SetValue, skew: float, option_skew: SetValue):
        try:
            self.SetMarkerMode(marker, mode)
            self.SetMarkerHighVoltage(marker, vhigh, option_vhigh)
            self.SetMarkerLowVoltage(marker, vlow, option_vlow)
            self.SetMarkerSkew(marker, skew, option_skew)
        except Exception as e: raise Exception(e)

    def ConfigureParametricSine(self, waveform_name: str, sampling_rate: int, autocalc_option: AutoCalcOption, wrap_around_state: State, common_cycles: int,
                            common_frequency: float, common_length: int, common_phase: float):
        try:
            self.SetParametricWaveformType(waveform_name, WaveType.Sine)
            self.SetAutoCalcOption(waveform_name, autocalc_option)
            if autocalc_option == AutoCalcOption.Length:
                self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
                self.SetParametricWaveformCommonCycles(waveform_name, common_cycles, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            elif autocalc_option == AutoCalcOption.SamplingRate:
                self.SetParametricWaveformCommonLength(waveform_name, common_length, SetValue.PRESENT)
                self.SetParametricWaveformCommonCycles(waveform_name, common_cycles, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            elif autocalc_option == AutoCalcOption.Cycles:
                self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
                self.SetParametricWaveformCommonLength(waveform_name, common_length, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            elif autocalc_option == AutoCalcOption.LengthAndCycles:
                self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            self.SetParametricWaveformCommonPhase(waveform_name, common_phase, SetValue.PRESENT)
            self.SetWrapAroundState(waveform_name, wrap_around_state)
        except Exception as e: raise Exception(e)

    def ConfigureParametricPulse(self, waveform_name: str, sampling_rate: int, autocalc_option: AutoCalcOption, wrap_around_state: State, common_cycles: int,
                        common_frequency: float, common_length: int, pulse_rise_time: float, pulse_fall_time: float, pulse_duty_cycle: float, pulse_delay: float):
        try:
            self.SetParametricWaveformType(waveform_name, WaveType.Pulse)
            self.SetAutoCalcOption(waveform_name, autocalc_option)
            if autocalc_option == AutoCalcOption.Length:
                self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
                self.SetParametricWaveformCommonCycles(waveform_name, common_cycles, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            elif autocalc_option == AutoCalcOption.SamplingRate:
                self.SetParametricWaveformCommonLength(waveform_name, common_length, SetValue.PRESENT)
                self.SetParametricWaveformCommonCycles(waveform_name, common_cycles, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            elif autocalc_option == AutoCalcOption.Cycles:
                self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
                self.SetParametricWaveformCommonLength(waveform_name, common_length, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            elif autocalc_option == AutoCalcOption.LengthAndCycles:
                self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            self.SetParametricWaveformPulseRiseTime(waveform_name, pulse_rise_time, SetValue.PRESENT)
            self.SetParametricWaveformPulseFallTime(waveform_name, pulse_fall_time, SetValue.PRESENT)
            self.SetParametricWaveformPulseDutyCycle(waveform_name, pulse_duty_cycle, SetValue.PRESENT)
            self.SetParametricWaveformPulseDelay(waveform_name, pulse_delay, SetValue.PRESENT)
            self.SetWrapAroundState(waveform_name, wrap_around_state)
        except Exception as e: raise Exception(e)
        
    def ConfigureParametricSweep(self, waveform_name: str, sampling_rate: int, length: int, start_frequency: float, stop_frequency: float, mode: SweepMode):
        try:
            self.SetParametricWaveformType(waveform_name, WaveType.Sweep)
            self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
            self.SetParametricWaveformCommonLength(waveform_name, length, SetValue.PRESENT)
            self.SetParametricWaveformSweepStartFrequency(waveform_name, start_frequency, SetValue.PRESENT)
            self.SetParametricWaveformSweepStopFrequency(waveform_name, stop_frequency, SetValue.PRESENT)
            self.SetParametricWaveformSweepMode(waveform_name, mode)
        except Exception as e: raise Exception(e)

    def ConfigureParametricSinc(self, waveform_name: str, sampling_rate: int, length: int, peak_position: float, lobe_width: float):
        try:
            self.SetParametricWaveformType(waveform_name, WaveType.Sinc)
            self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
            self.SetParametricWaveformCommonLength(waveform_name, length, SetValue.PRESENT)
            self.SetParametricWaveformSincLobePeakPosition(waveform_name, peak_position, SetValue.PRESENT)
            self.SetParametricWaveformSincLobeWidth(waveform_name, lobe_width,SetValue.PRESENT)
        except Exception as e: raise Exception(e)

    def ConfigureParametricExponential(self, waveform_name: str, sampling_rate: int, length: int, cycles: int, time_constant: float, mode:ExpMode):
        try:
            self.SetParametricWaveformType(waveform_name, WaveType.Exponential)
            self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
            self.SetParametricWaveformCommonLength(waveform_name, length, SetValue.PRESENT)
            self.SetParametricWaveformCommonCycles(waveform_name, cycles, SetValue.PRESENT)
            self.SetParametricWaveformExpTimeConstant(waveform_name, time_constant, SetValue.PRESENT)
            self.SetParametricWaveformExpMode(waveform_name, mode)
        except Exception as e: raise Exception(e)

    def ConfigureParametricPRBS(self, waveform_name: str, sampling_rate: int, length: int, type:PRBSType):
        try:
            self.SetParametricWaveformType(waveform_name, WaveType.PRBS)
            self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
            self.SetParametricWaveformCommonLength(waveform_name, length, SetValue.PRESENT)
            self.SetParametricWaveformPrbsType(waveform_name, type)
        except Exception as e: raise Exception(e)
        
    def ConfigureParametricSquare(self, waveform_name: str, sampling_rate: int, autocalc_option: AutoCalcOption, wrap_around_state: State, common_cycles: int,
                        common_frequency: float, common_length: int, rise_time: float, fall_time: float, delay: float):
        try:
            self.SetParametricWaveformType(waveform_name, WaveType.Square)
            self.SetAutoCalcOption(waveform_name, autocalc_option)
            if autocalc_option == AutoCalcOption.Length:
                self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
                self.SetParametricWaveformCommonCycles(waveform_name, common_cycles, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            elif autocalc_option == AutoCalcOption.SamplingRate:
                self.SetParametricWaveformCommonLength(waveform_name, common_length, SetValue.PRESENT)
                self.SetParametricWaveformCommonCycles(waveform_name, common_cycles, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            elif autocalc_option == AutoCalcOption.Cycles:
                self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
                self.SetParametricWaveformCommonLength(waveform_name, common_length, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            elif autocalc_option == AutoCalcOption.LengthAndCycles:
                self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
                self.SetParametricWaveformCommonFrequency(waveform_name, common_frequency, SetValue.PRESENT)
            self.SetParametricWaveformSquareRiseTime(waveform_name, rise_time, SetValue.PRESENT)
            self.SetParametricWaveformSquareFallTime(waveform_name, fall_time, SetValue.PRESENT)
            self.SetParametricWaveformSquarePDelay(waveform_name, delay, SetValue.PRESENT)
            self.SetWrapAroundState(waveform_name, wrap_around_state)
        except Exception as e: raise Exception(e)

    def ConfigureParametricMultitone(self, waveform_name: str, sampling_rate: int, tone_list: List[List[float]]):
        try:
            """Tone list must be a list of lists (matrix) like: [<frequency>, <amplitude>, <phase>]
            Example of tone_list of three tones:
            tone_list = [[10000, 1, 0],
                          [1000, 0.4, 0],
                          [100000, 0.8, 2]]"""
            self.SetParametricWaveformType(waveform_name, WaveType.Multitone)
            self.SetParametricWaveformCommonSamplingRate(waveform_name, sampling_rate, SetValue.PRESENT)
            if len(tone_list) > 10: raise Exception("Matrix must be at most 10 tones long")
            else:
                for tone in tone_list: self.AddNewToneParametricWave(waveform_name, SetValue.PRESENT, SetValue.PRESENT, SetValue.PRESENT, tone[0], tone[1], tone[2])
        except Exception as e: raise Exception(e)

    def ConfigureTiming(self, clock_source: ClockSource, sampling_clock: float, sampling_clock_value: SetValue, ext_clk_divisor: ExtClkDivisor, ref_clk_freq: float,
                        ref_clk_freq_option: SetValue, synch_clk_out_state: State, sync_clk_out_selector: SyncClockOutSelector, low_jitter_state: State):
        try:
            self.SetClockSource(clock_source)
            self.SetSamplingClockFrequency(sampling_clock, sampling_clock_value)
            if clock_source == ClockSource.External: self.SetExternalClockDivisor(ext_clk_divisor)
            elif clock_source == ClockSource.Reference:
                self.SetReferenceClockFrequency(ref_clk_freq, ref_clk_freq_option)
                self.SetLowJitterTriggerState(low_jitter_state)
            self.SetSyncClockOutState(synch_clk_out_state)
            if synch_clk_out_state == State.ON: self.SetSyncClockOutSelector(sync_clk_out_selector)
        except Exception as e: raise Exception(e)

    def ConfigureTriggerIn(self, trigger_source: TriggerInSource, interval: float, interval_minmax: SetValue, thresholds: List[float], slopes: List[Slope], impedances: List[Impedance],
                           timing_modes: List[TriggerTiming], delays: List[float]):
        try:
            if self.GetRunMode() == "ADVAnced":
                triggers = [TriggerIn.TriggerIn1, TriggerIn.TriggerIn2, TriggerIn.TriggerIn3, TriggerIn.TriggerIn4]
                self.SetTriggerInterval(interval, interval_minmax)
                for i in range(len(triggers)):
                    self.SetTriggerThreshold(triggers[i], thresholds[i], SetValue.PRESENT)
                    self.SetTriggerEdge(triggers[i], slopes[i])
                    self.SetTriggerImpedance(triggers[i], impedances[i])
                    self.SetTriggerTimingMode(triggers[i], timing_modes[i])
                    self.SetTriggerDelayAdjust(triggers[i], delays[i], SetValue.PRESENT)
                    if i == 1 and self.GetChannelsOutputNumber() != "4": break
            else:
                self.SetTriggerSource(trigger_source)
                if trigger_source == TriggerInSource.ExtTriggerIn:
                    self.SetTriggerThreshold(TriggerIn.TriggerIn1, thresholds[0], SetValue.PRESENT)
                    self.SetTriggerEdge(TriggerIn.TriggerIn1, slopes[0])
                    self.SetTriggerImpedance(TriggerIn.TriggerIn1, impedances[0])
                    self.SetTriggerTimingMode(TriggerIn.TriggerIn1, timing_modes[0])
                    self.SetTriggerDelayAdjust(TriggerIn.TriggerIn1, delays[0], SetValue.PRESENT)
                elif trigger_source == TriggerInSource.Timer: self.SetTriggerInterval(interval, interval_minmax)
        except Exception as e: raise Exception(e)


    #Sequencer elements
    def ConfigureSequencerElement(self, entry: SequencerEntry):
        try:
            if entry.repetitions == 0: self.SetEntryRepetitions(entry.entry_number, entry.repetitions, SetValue2.INFINITE)
            else: self.SetEntryRepetitions(entry.entry_number, entry.repetitions, SetValue2.PRESENT)
            self.ChangeFormat(Format.Amplitude_offset)
            for i in range(len(entry.analog_waveform_names)):
                if i % 2 != 0: self.SetChannelWaveform(entry.entry_number, self.channels[i], entry.analog_waveform_names[i], OutputFormat.Waveform)
                else: self.SetChannelWaveform(entry.entry_number, self.channels[i], entry.analog_waveform_names[i], entry.output_formats[i])

                self.SetEntryLength(entry.entry_number, entry.length, SetValue.PRESENT)

                if i % 2 != 0 and entry.output_formats[i] == OutputFormat.Waveform:
                    self.SetChannelAmplitude(entry.entry_number, self.channels[i], entry.amplitudes[i], SetValue.PRESENT)
                    self.SetChannelOffset(entry.entry_number, self.channels[i], entry.offsets[i], SetValue.PRESENT)
                    if entry.sub_lengths[i] <= int(self.GetWaveformLength(entry.analog_waveform_names[i], GetValue.PRESENT)): self.SetChannelIncreasingStrategy(entry.increasing_strategies[i])
                    else: self.SetChannelDecreasingStrategy(entry.decreasing_strategies[i])
                    self.SetChannelSubLength(entry.entry_number, self.channels[i], entry.sub_lengths[i], SetValue.PRESENT)
                    self.SetChannelDelay(entry.entry_number, self.channels[i], entry.delays[i], SetValue.PRESENT)

            license = self.CheckQuery("*OPT?")
            if not "No Digitals" in license and entry.digital_waveform_name != "":
                self.SetChannelWaveform(entry.entry_number, ChannelEntry.Digital, entry.digital_waveform_name, OutputFormat.Waveform)
            if entry.custom_pattern != "":
                self.SetChannelWaveform(entry.entry_number, ChannelEntry.ProgrammedMarker, entry.custom_pattern, OutputFormat.Waveform)
        except Exception as e: raise Exception(e)


    def ConfigureAdvancedSequencerElement(self, format: Format, entry: AdvancedSequencerEntry):
        try:
            self.ChangeFormat(format)
            for i in range(len(entry.analog_waveform_names)):
                if i % 2 != 0: self.SetChannelWaveform(entry.entry_number, self.channels[i], entry.analog_waveform_names[i], OutputFormat.Waveform)
                else: self.SetChannelWaveform(entry.entry_number, self.channels[i], entry.analog_waveform_names[i], entry.output_formats[i])

                if i % 2 != 0 and entry.output_formats[i] == OutputFormat.Waveform:
                    self.SetChannelAmplitude(entry.entry_number, self.channels[i], entry.amplitudes[i], SetValue.PRESENT)
                    self.SetChannelOffset(entry.entry_number, self.channels[i], entry.offsets[i], SetValue.PRESENT)
                    if entry.sub_lengths[i] <= int(self.GetWaveformLength(entry.analog_waveform_names[i], GetValue.PRESENT)): self.SetChannelIncreasingStrategy(entry.increasing_strategies[i])
                    else: self.SetChannelDecreasingStrategy(entry.decreasing_strategies[i])
                    self.SetChannelSubLength(entry.entry_number, self.channels[i], entry.sub_lengths[i], SetValue.PRESENT)
                    self.SetChannelDelay(entry.entry_number, self.channels[i], entry.delays[i], SetValue.PRESENT)

            license = self.CheckQuery("*OPT?")
            if not "No Digitals" in license and entry.digital_waveform_name != "":
                self.SetChannelWaveform(entry.entry_number, ChannelEntry.Digital, entry.digital_waveform_name, OutputFormat.Waveform)
            if entry.custom_pattern != "":
                self.SetChannelWaveform(entry.entry_number, ChannelEntry.ProgrammedMarker, entry.custom_pattern, OutputFormat.Waveform)        
            
            self.SetEntryLength(entry.entry_number, entry.length, SetValue.PRESENT)
            if entry.repetitions == 0: self.SetEntryRepetitions(entry.entry_number, entry.repetitions, SetValue2.INFINITE)
            else: self.SetEntryRepetitions(entry.entry_number, entry.repetitions, SetValue2.PRESENT)
            self.SetEntryWaitEvent(entry.entry_number, entry.wait_event)
            self.SetEntryJumpEvent(entry.entry_number, entry.jump_event)
            self.SetEntryJumpToMode(entry.entry_number, entry.jump_to_mode)
            self.SetEntryJumpToltem(entry.entry_number, entry.jump_to_entry_item, SetValue.PRESENT)
            self.SetEntryGoToMode(entry.entry_number, entry.go_to_mode)
            self.SetEntryGoToltem(entry.entry_number, entry.go_to_entry_item, SetValue.PRESENT)
            self.SetEntryPatternMode(entry.entry_number, entry.pattern_mode)
            self.SetEntryPatternCode(entry.entry_number, entry.pattern_code, SetValue.PRESENT)
            self.SetEntryPatternJumpToItem(entry.entry_number, entry.pattern_jump_to_entry, SetValue.PRESENT)
        except Exception as e: raise Exception(e)