@@ -1539,6 +1539,97 @@ def piecewise_accel_ramp(self, t, duration, initial, final, samplerate, units=No
15391539 'initial time' : t , 'end time' : t + truncation * duration , 'clock rate' : samplerate , 'units' : units })
15401540 return truncation * duration
15411541
1542+ def square_wave (self , t , duration , level_0 , level_1 , frequency , phase ,
1543+ duty_cycle , samplerate , units = None , truncation = 1. ):
1544+ """A standard square wave.
1545+
1546+ This method generates a square wave which starts at `level_0` (when its
1547+ phase is zero) then transitions to/from `level_1` at the specified
1548+ `frequency`.
1549+
1550+ Note that because the transitions of a square wave are sudden and
1551+ discontinuous, small changes in timings (e.g. due to numerical rounding
1552+ errors) can affect the output value. This is particularly relevant at
1553+ the end of the waveform, as the final output value may be different than
1554+ expected if the end of the waveform is close to an edge of the square
1555+ wave. Care is taken in the implementation of this method to avoid such
1556+ effects, but it still may be desirable to call `constant()` after
1557+ `square_wave()` to ensure a particular final value. The output value may
1558+ also be different than expected at certain moments in the middle of the
1559+ waveform due to the finite samplerate (which may be different than the
1560+ requested `samplerate`), particularly if the actual samplerate is not a
1561+ multiple of `frequency`.
1562+
1563+ Args:
1564+ t (float): The time at which to start the square wave.
1565+ duration (float): The duration for which to output a square wave
1566+ (assuming `truncation=1.0`).
1567+ level_0 (float): The initial level of the square wave, when the
1568+ phase is zero.
1569+ level_1 (float): The other level of the square wave.
1570+ frequency (float): The frequency of the square wave, in Hz.
1571+ phase (float): The initial phase of the square wave. Note that the
1572+ square wave is defined such that the phase goes from 0 to 1 (NOT
1573+ 2 pi) over one cycle, so setting `phase=0.5` will start the
1574+ square wave advanced by 1/2 of a cycle. Setting `phase` to be
1575+ `1 - duty_cycle` will cause the waveform to start at `level_1`
1576+ rather than `level_0`.
1577+ duty_cycle (float): The fraction of the cycle for which the output
1578+ should be set to `level_1`. This should be a number between zero
1579+ and one inclusively. For example, setting `duty_cycle=0.1` will
1580+ create a square wave which outputs `level_0` over 90% of the
1581+ cycle and outputs `level_1` over 10% of the cycle.
1582+ samplerate (float): The requested rate at which to update the output
1583+ value. Note that the actual samplerate used may be different if,
1584+ for example, another output of the same device has a
1585+ simultaneous ramp with a different requested `samplerate`, or if
1586+ `1 / samplerate` isn't an integer multiple of the pseudoclock's
1587+ timing resolution.
1588+ units (str, optional): The units of the output values. If set to
1589+ `None` then the output's base units will be used. Defaults to
1590+ `None`.
1591+ truncation (float, optional): The actual duration of the square wave
1592+ will be `duration * truncation` and `truncation` must be set to
1593+ a value in the range [0, 1] (inclusively). Set to `1` to output
1594+ the full duration of the square wave. Setting it to `0` will
1595+ skip the square wave entirely. Defaults to `1.`.
1596+
1597+ Returns:
1598+ duration (float): The actual duration of the square wave, accounting
1599+ for `truncation`.
1600+ """
1601+ # Check the argument values.
1602+ self ._check_truncation (truncation )
1603+ if duty_cycle < 0 or duty_cycle > 1 :
1604+ msg = """Square wave duty cycle must be in the range [0, 1]
1605+ (inclusively) but was set to {duty_cycle}.""" .format (
1606+ duty_cycle = duty_cycle
1607+ )
1608+ raise LabscriptError (dedent (msg ))
1609+
1610+ if truncation > 0 :
1611+ # Add the instruction.
1612+ func = functions .square_wave (
1613+ round (t + duration , 10 ) - round (t , 10 ),
1614+ level_0 ,
1615+ level_1 ,
1616+ frequency ,
1617+ phase ,
1618+ duty_cycle ,
1619+ )
1620+ self .add_instruction (
1621+ t ,
1622+ {
1623+ 'function' : func ,
1624+ 'description' : 'square wave' ,
1625+ 'initial time' : t ,
1626+ 'end time' : t + truncation * duration ,
1627+ 'clock rate' : samplerate ,
1628+ 'units' : units ,
1629+ }
1630+ )
1631+ return truncation * duration
1632+
15421633 def customramp (self , t , duration , function , * args , ** kwargs ):
15431634 units = kwargs .pop ('units' , None )
15441635 samplerate = kwargs .pop ('samplerate' )
0 commit comments