def __init__(self, td, Amplitude=1., StartTime=0., risetime=0.): """Constructor constructs a step waveform. @param td instance of class TimeDescriptor containing time axis of waveform. @param Amplitude (optional) float amplitude of step (defaults to unity). @param StartTime (optional) float starting time of the pulse (defaults to zero). @param risetime (optional) float risetime in seconds (defaults to 0.) @note The amplitude can be positive or negative, with negative providing a negative pulse. @note The step starts at the first sample point after the start time specified. @note actual risetime used is the sample period if less than that is specified @note the risetime is applied such that the step reaches half amplitude at the start time specified. Please note the expected non-causality. """ x = [0 if t < StartTime else Amplitude for t in td.Times()] T = risetime / self.rtvsT rcStart = max(0, td.IndexOfTime(StartTime - T / 2.)) if td.TimeOfPoint(rcStart) < StartTime - T / 2: rcStart = min(rcStart + 1, len(td) - 1) rcEnd = min(len(td) - 1, td.IndexOfTime(StartTime + T / 2.)) if td.TimeOfPoint(rcEnd) > StartTime + T / 2: rcEnd = max(rcEnd - 1, 0) for i in range(rcStart, rcEnd + 1): try: x[i]=Amplitude*\ (math.sin((td.TimeOfPoint(i)-StartTime)/T*math.pi)+1.)/2. except ZeroDivisionError: pass Waveform.__init__(self, td, x)
def __init__(self, td, Amplitude=1., StartTime=0., PulseWidth=0., Risetime=0.): """Constructor constructs a waveform with a single pulse. @param td instance of class TimeDescriptor containing time axis of waveform. @param Amplitude (optional) float amplitude of pulse (defaults to unity). @param StartTime (optional) float starting time of the pulse (defaults to zero). @param PulseWidth (optional) float the width of the pulse (defaults to zero). @param Risetime (optional) float risetime in seconds (defaults to 0.) @note The amplitude can be positive or negative, with negative providing a negative pulse. @note if the pulse appears entirely within the samples, then the waveform will be all zero. @note actual risetime used is the sample period if less than that is specified @note risetime is applied on the rising and falling edge. risetimes greater than 1.72 times the pulse width will diminish the pulse amplitude. @note the risetime is applied such that the pulse reaches half amplitude at the start time specified. Please note the expected non-causality. """ StopTime = StartTime + PulseWidth stepup = StepWaveform(td, Amplitude, StartTime, Risetime) stepdown = StepWaveform(td, Amplitude, StopTime, Risetime) Waveform.__init__( self, td, [stepup[k] - stepdown[k] for k in range(len(stepup))])
def __init__(self, td, Amplitude=1., Frequency=1e6, Phase=0., StartTime=-100., StopTime=100.): """Constructor constructs a sinewave waveform. @param td instance of class TimeDescriptor containing time axis of waveform. @param Amplitude (optional) float amplitude of sine wave (defaults to unity). @param Frequency (optional) float frequency of sine wave (defaults to 1 MHz). @param Phase (optional) float phase of sine wave in degrees (defaults to zero). @param StartTime (optional) float start time of sine wave (defaults to -100 s). @param StopTime (optional) float stop time of the sine wave (defaults to 100 s). """ x = [ Amplitude * math.sin(2. * math.pi * Frequency * t + Phase / 180. * math.pi) for t in td.Times() ] sw = Waveform(td, x) * PulseWaveform( td, Amplitude=1., StartTime=StartTime, PulseWidth=max(StartTime, StopTime) - min(StartTime, StopTime), Risetime=0.) Waveform.__init__(self, sw.td, sw.Values())
def __init__(self,pattern,bitRate,amplitude=1.0,risetime=0.,delay=0.,tdOrFs=None): """constructor @param pattern list of bits in pattern which must be 0 or 1 @param bitrate float bitrate in bits/s @param amplitude (optional, defaults to 1.0) float amplitude of zero centered serial data waveform (pk-pk amplitude is twice this value) @param risetime (optional, defaults to 0.0) float risetime of a 1/2 cosine response. @param delay (optional, defaults to 0,0) float delay in time into the pattern. @param tdOrFs (optional, defaults to None) time descriptor or float sample rate. If None is specified, then the descriptor is generated for one pattern length with a sample rate of 10x the bitrate. Otherwise, if a float is specified, then a time descriptor for one pattern length is generated with the sample rate specified. Otherwise the time descriptor specified is used. @return self, a waveform. @throw SignalIntegrityExceptionWaveform exception is raised if the risetime exceeds 59% of the unit interval as this causes the calculation to fail. @todo the failure for a given risetime is due to the simplicity of the algorithm which should be improved at some point. this simplicity is that it only looks at adjacent bits to determine the intersymbol effect of the risetime. @note the left edge of the first bit in the pattern is at the delay time. But because a cosine is used for the risetime emulation, the 50% point of the cosine is reached at this edge. @note the risetime is adjusted if it is too low relative to the sample period. """ if tdOrFs is None: sampleRate=10.*bitRate td=self.TimeDescriptor(bitRate, sampleRate, len(pattern)) elif isinstance(tdOrFs,float): sampleRate=tdOrFs td=self.TimeDescriptor(bitRate, sampleRate, len(pattern)) else: td=tdOrFs T=max(risetime/self.rtvsT,1/td.Fs) patternTimeLength=len(pattern)/bitRate unitInterval=1./bitRate if T>unitInterval: # todo: would like to handle this case in the future raise SignalIntegrityExceptionWaveform('PRBS risetime too high\nfor waveform generation. '+\ 'Limit is '+ToSI(unitInterval*self.rtvsT,'s')+' for given bitrate') v=[0. for _ in range(len(td))] for k in range(len(td)): t=td[k] timeInPattern=((t-delay)%patternTimeLength+patternTimeLength)%patternTimeLength thisBit=int(math.floor(timeInPattern/unitInterval)) timeInBit=timeInPattern-thisBit*unitInterval thisBitValue=pattern[thisBit] if timeInBit>=T/2. and (timeInBit-unitInterval)<=-T/2.: v[k]=2.*amplitude*(thisBitValue-0.5) elif timeInBit<T/2.: previousBit=(thisBit-1+len(pattern))%len(pattern) previousBitTransition=thisBitValue-pattern[previousBit] if previousBitTransition==0: v[k]=2.*amplitude*(thisBitValue-0.5) else: v[k]=amplitude*previousBitTransition*math.cos(math.pi*(timeInBit/T+3./2.)) elif (timeInBit-unitInterval)>-T/2.: nextBit=(thisBit+1)%len(pattern) nextBitTransition=pattern[nextBit]-thisBitValue if nextBitTransition==0: v[k]=2.*amplitude*(thisBitValue-0.5) else: v[k]=amplitude*nextBitTransition*math.cos(math.pi*((timeInBit-unitInterval)/T+3./2.)) Waveform.__init__(self,Waveform(td,v))
def __init__(self, td, sigma, mean=0.0): """Constructor constructs a waveform with mean and normally distributed noise. @param td instance of class TimeDescriptor containing time axis of waveform. @param sigma float non-zero value of the rms value of the noise @param mean (optional) float containing the mean value of the waveform """ Waveform.__init__(self, td, numpy.random.normal(mean, sigma, int(td.K)).tolist())
def __init__(self, t=None, td=None): """constructor @param t instance of class TimeDescriptor describing time-axis of impulse response @param td list of float representing time-domain values @remark note that t can be an instance of waveform and td None which causes the impulse response to be instantiated dircectly from a waveform. """ if isinstance(t, Waveform): Waveform.__init__(self, t.td, t) else: Waveform.__init__(self, t, td)
def __init__(self,td,Amplitude=1.,StartTime=0.): """Constructor constructs a step waveform. @param td instance of class TimeDescriptor containing time axis of waveform. @param Amplitude (optional) float amplitude of step (defaults to unity). @param StartTime (optional) float starting time of the pulse (defaults to zero). @note The amplitude can be positive or negative, with negative providing a negative pulse. @note The step starts at the first sample point after the start time specified. """ x=[0 if t < StartTime else Amplitude for t in td.Times()] Waveform.__init__(self,td,x)
def __init__(self, td, Amplitude=1., StartTime=0., PulseWidth=0): """Constructor constructs a waveform with mean and normally distributed noise. @param td instance of class TimeDescriptor containing time axis of waveform. @param Amplitude (optional) float amplitude of pulse (defaults to unity). @param StartTime (optional) float starting time of the pulse (defaults to zero). @param PulseWidth (optional) float the width of the pulse (defaults to zero). @note The amplitude can be positive or negative, with negative providing a negative pulse. @note if the pulse appears entirely within the samples, then the waveform will be all zero. """ StopTime = StartTime + PulseWidth stepup = StepWaveform(td, Amplitude, StartTime) stepdown = StepWaveform(td, Amplitude, StopTime) Waveform.__init__( self, td, [stepup[k] - stepdown[k] for k in range(len(stepup))])
def __init__(self, sp, port=1, method='exact', align='middle', includePortZ=True, adjustForDelay=True): """Constructor @param sp instance of class SParameters of the device @param port (optional) integer 1 based port number (defaults to port 1) @param method (optional) string method for computation (defaults to 'exact') @param align (optional) string alignment of impedancance in waveform (defaults to 'middle') @param includePortZ (optional) boolean whether to put the port reference impedance as the first point. (defaults to True) @param adjustForDelay (optional) boolean whether to adjust for the delay in the impulse response (defaults to True) @remark computation methods include: 'exact' (default) - calculates using reflection coefficient of first point computed from DFT and deembedding. (this method takes longer and can diverge due to buildup of numerical inaccuracies.) 'estimated' - calculates the reflection coefficients directly from the step response. 'approximate' - calculates the reflection coefficients from the step response using an approximation. @remark alignment methods include: 'middle' (default) - shows the impedance in the middle of the sample period distance along the line. 'front' - shows the impedance measured at the front of the line. """ tdsp = sp.m_f.TimeDescriptor() # assumes middle and no portZ tdip = TimeDescriptor(1. / (tdsp.Fs * 4), tdsp.K / 2, tdsp.Fs * 2) if not align == 'middle': tdip.H = tdip.H - 1. / (tdsp.Fs * 4) if method == 'exact': ip = ImpedanceProfile(sp, tdip.K, port) Z = ip.Z() delayAdjust = ip.m_fracD elif method == 'estimated' or method == 'approximate': fr = sp.FrequencyResponse(port, port) rho = fr.ImpulseResponse().Integral(addPoint=True, scale=False) delayAdjust = fr._FractionalDelayTime() finished = False for m in range(len(rho)): if finished: rho[m] = rho[m - 1] continue rho[m] = max(-self.rhoLimit, min(self.rhoLimit, rho[m])) if abs(rho[m]) == self.rhoLimit: finished = True if method == 'estimated': Z = [ max( 0., min( sp.m_Z0 * (1 + rho[tdsp.K // 2 + 1 + k]) / (1 - rho[tdsp.K // 2 + 1 + k]), self.ZLimit)) for k in range(tdip.K) ] else: Z = [ max( 0., min(sp.m_Z0 + 2 * sp.m_Z0 * rho[tdsp.K // 2 + 1 + k], self.ZLimit)) for k in range(tdip.K) ] if includePortZ: tdip.H = tdip.H - 1. / (tdsp.Fs * 2) tdip.K = tdip.K + 1 Z = [sp.m_Z0] + Z if adjustForDelay: tdip.H = tdip.H + delayAdjust / 2 Waveform.__init__(self, tdip, Z)