@@ -1974,6 +1974,178 @@ def piecewise_accel_ramp(self, t, duration, initial, final, samplerate, units=No
19741974 'initial time' : t , 'end time' : t + truncation * duration , 'clock rate' : samplerate , 'units' : units })
19751975 return truncation * duration
19761976
1977+ def square_wave (self , t , duration , amplitude , frequency , phase , offset ,
1978+ duty_cycle , samplerate , units = None , truncation = 1. ):
1979+ """A standard square wave.
1980+
1981+ This method generates a square wave which starts HIGH (when its phase is
1982+ zero) then transitions to/from LOW at the specified `frequency` in Hz.
1983+ The `amplitude` parameter specifies the peak-to-peak amplitude of the
1984+ square wave which is centered around `offset`. For example, setting
1985+ `amplitude=1` and `offset=0` would give a square wave which transitions
1986+ between `0.5` and `-0.5`. Similarly, setting `amplitude=2` and
1987+ `offset=3` would give a square wave which transitions between `4` and
1988+ `2`. To instead specify the HIGH/LOW levels directly, use
1989+ `square_wave_levels()`.
1990+
1991+ Note that because the transitions of a square wave are sudden and
1992+ discontinuous, small changes in timings (e.g. due to numerical rounding
1993+ errors) can affect the output value. This is particularly relevant at
1994+ the end of the waveform, as the final output value may be different than
1995+ expected if the end of the waveform is close to an edge of the square
1996+ wave. Care is taken in the implementation of this method to avoid such
1997+ effects, but it still may be desirable to call `constant()` after
1998+ `square_wave()` to ensure a particular final value. The output value may
1999+ also be different than expected at certain moments in the middle of the
2000+ waveform due to the finite samplerate (which may be different than the
2001+ requested `samplerate`), particularly if the actual samplerate is not a
2002+ multiple of `frequency`.
2003+
2004+ Args:
2005+ t (float): The time at which to start the square wave.
2006+ duration (float): The duration for which to output a square wave
2007+ when `truncation` is set to `1`. When `truncation` is set to a
2008+ value less than `1`, the actual duration will be shorter than
2009+ `duration` by that factor.
2010+ amplitude (float): The peak-to-peak amplitude of the square wave.
2011+ See above for an example of how to calculate the HIGH/LOW output
2012+ values given the `amplitude` and `offset` values.
2013+ frequency (float): The frequency of the square wave, in Hz.
2014+ phase (float): The initial phase of the square wave. Note that the
2015+ square wave is defined such that the phase goes from 0 to 1 (NOT
2016+ 2 pi) over one cycle, so setting `phase=0.5` will start the
2017+ square wave advanced by 1/2 of a cycle. Setting `phase` equal to
2018+ `duty_cycle` will cause the waveform to start LOW rather than
2019+ HIGH.
2020+ offset (float): The offset of the square wave, which is the value
2021+ halfway between the LOW and HIGH output values. Note that this
2022+ is NOT the LOW output value; setting `offset` to `0` will cause
2023+ the HIGH/LOW values to be symmetrically split around `0`. See
2024+ above for an example of how to calculate the HIGH/LOW output
2025+ values given the `amplitude` and `offset` values.
2026+ duty_cycle (float): The fraction of the cycle for which the output
2027+ should be HIGH. This should be a number between zero and one
2028+ inclusively. For example, setting `duty_cycle=0.1` will
2029+ create a square wave which outputs HIGH over 10% of the
2030+ cycle and outputs LOW over 90% of the cycle.
2031+ samplerate (float): The requested rate at which to update the output
2032+ value. Note that the actual samplerate used may be different if,
2033+ for example, another output of the same device has a
2034+ simultaneous ramp with a different requested `samplerate`, or if
2035+ `1 / samplerate` isn't an integer multiple of the pseudoclock's
2036+ timing resolution.
2037+ units (str, optional): The units of the output values. If set to
2038+ `None` then the output's base units will be used. Defaults to
2039+ `None`.
2040+ truncation (float, optional): The actual duration of the square wave
2041+ will be `duration * truncation` and `truncation` must be set to
2042+ a value in the range [0, 1] (inclusively). Set to `1` to output
2043+ the full duration of the square wave. Setting it to `0` will
2044+ skip the square wave entirely. Defaults to `1.`.
2045+
2046+ Returns:
2047+ duration (float): The actual duration of the square wave, accounting
2048+ for `truncation`.
2049+ """
2050+ # Convert to values used by square_wave_levels, then call that method.
2051+ level_0 = offset + 0.5 * amplitude
2052+ level_1 = offset - 0.5 * amplitude
2053+ return self .square_wave_levels (
2054+ t ,
2055+ duration ,
2056+ level_0 ,
2057+ level_1 ,
2058+ frequency ,
2059+ phase ,
2060+ duty_cycle ,
2061+ samplerate ,
2062+ units ,
2063+ truncation ,
2064+ )
2065+
2066+ def square_wave_levels (self , t , duration , level_0 , level_1 , frequency ,
2067+ phase , duty_cycle , samplerate , units = None ,
2068+ truncation = 1. ):
2069+ """A standard square wave.
2070+
2071+ This method generates a square wave which starts at `level_0` (when its
2072+ phase is zero) then transitions to/from `level_1` at the specified
2073+ `frequency`. This is the same waveform output by `square_wave()`, but
2074+ parameterized differently. See that method's docstring for more
2075+ information.
2076+
2077+ Args:
2078+ t (float): The time at which to start the square wave.
2079+ duration (float): The duration for which to output a square wave
2080+ when `truncation` is set to `1`. When `truncation` is set to a
2081+ value less than `1`, the actual duration will be shorter than
2082+ `duration` by that factor.
2083+ level_0 (float): The initial level of the square wave, when the
2084+ phase is zero.
2085+ level_1 (float): The other level of the square wave.
2086+ frequency (float): The frequency of the square wave, in Hz.
2087+ phase (float): The initial phase of the square wave. Note that the
2088+ square wave is defined such that the phase goes from 0 to 1 (NOT
2089+ 2 pi) over one cycle, so setting `phase=0.5` will start the
2090+ square wave advanced by 1/2 of a cycle. Setting `phase` equal to
2091+ `duty_cycle` will cause the waveform to start at `level_1`
2092+ rather than `level_0`.
2093+ duty_cycle (float): The fraction of the cycle for which the output
2094+ should be set to `level_0`. This should be a number between zero
2095+ and one inclusively. For example, setting `duty_cycle=0.1` will
2096+ create a square wave which outputs `level_0` over 10% of the
2097+ cycle and outputs `level_1` over 90% of the cycle.
2098+ samplerate (float): The requested rate at which to update the output
2099+ value. Note that the actual samplerate used may be different if,
2100+ for example, another output of the same device has a
2101+ simultaneous ramp with a different requested `samplerate`, or if
2102+ `1 / samplerate` isn't an integer multiple of the pseudoclock's
2103+ timing resolution.
2104+ units (str, optional): The units of the output values. If set to
2105+ `None` then the output's base units will be used. Defaults to
2106+ `None`.
2107+ truncation (float, optional): The actual duration of the square wave
2108+ will be `duration * truncation` and `truncation` must be set to
2109+ a value in the range [0, 1] (inclusively). Set to `1` to output
2110+ the full duration of the square wave. Setting it to `0` will
2111+ skip the square wave entirely. Defaults to `1.`.
2112+
2113+ Returns:
2114+ duration (float): The actual duration of the square wave, accounting
2115+ for `truncation`.
2116+ """
2117+ # Check the argument values.
2118+ self ._check_truncation (truncation )
2119+ if duty_cycle < 0 or duty_cycle > 1 :
2120+ msg = """Square wave duty cycle must be in the range [0, 1]
2121+ (inclusively) but was set to {duty_cycle}.""" .format (
2122+ duty_cycle = duty_cycle
2123+ )
2124+ raise LabscriptError (dedent (msg ))
2125+
2126+ if truncation > 0 :
2127+ # Add the instruction.
2128+ func = functions .square_wave (
2129+ round (t + duration , 10 ) - round (t , 10 ),
2130+ level_0 ,
2131+ level_1 ,
2132+ frequency ,
2133+ phase ,
2134+ duty_cycle ,
2135+ )
2136+ self .add_instruction (
2137+ t ,
2138+ {
2139+ 'function' : func ,
2140+ 'description' : 'square wave' ,
2141+ 'initial time' : t ,
2142+ 'end time' : t + truncation * duration ,
2143+ 'clock rate' : samplerate ,
2144+ 'units' : units ,
2145+ }
2146+ )
2147+ return truncation * duration
2148+
19772149 def customramp (self , t , duration , function , * args , ** kwargs ):
19782150 """Define a custom function for the output.
19792151
0 commit comments