@@ -1974,6 +1974,178 @@ def piecewise_accel_ramp(self, t, duration, initial, final, samplerate, units=No
1974
1974
'initial time' : t , 'end time' : t + truncation * duration , 'clock rate' : samplerate , 'units' : units })
1975
1975
return truncation * duration
1976
1976
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
+
1977
2149
def customramp (self , t , duration , function , * args , ** kwargs ):
1978
2150
"""Define a custom function for the output.
1979
2151
0 commit comments