Closed svilches closed 4 years ago
Here is an example how to do this:
from pyrpl import Pyrpl
from pyrpl.async_utils import sleep
import numpy as np
import time
%matplotlib inline
import matplotlib.pyplot as plt
p = Pyrpl(config='', hostname="rp", gui=False)
asg = p.rp.asg0
scope = p.rp.scope
# user constants
fsweep = 5000 # Frequency of repetition of the ramp
decimation = 8
sampleClock =125e6
buffSize = asg.data_length # 2**14
fs = sampleClock/decimation # sampling frequency
buffTime = buffSize / fs # Max acquisition time
n = (int)(fs / fsweep) # number of datapoints per ramp
scope.setup(
input1='asg0', # can directly look at asg signal, no need to output it (though you could)
average=True,
duration=0.001, # another way to specify decimation indirectly by the total trace duration
# the asg generates a digital trigger signal when it crosses index=0 of its waveform, which we trigger on with the asg0-setting
trigger_source='asg0',
# trigger_delay is not needed, since we start acquisition when the signal starts (i.e. trigger_delay=0)
# trigger_delay = self.buffTime/2
# the settings dont matter because trigger_source is not "ch1_positive_edge"
# threshold=0,
# hysteresis=0.01,
)
# set asg to something harmless - DC with 0 volts
asg.setup(
output_direct='off',
frequency=fsweep, # repetition rate of the waveform (assuming 2**14 points)
amplitude=1, # amplitude = 1 => custom waveform gets multiplied by unity on the FPGA
offset=0, # no offset, so we faithfully reproduce the waveform
waveform='dc', # choose DC, so the waveform is zero to start with
trigger_source='immediately', # I think mostly this setting was missing in your example -> asg never started
)
# replace asg data with custom waveform
waveform = np.linspace(-0.5, 0.5, n)
asg.data = waveform
# important: n is only slightly larger than 3000 with above parameters
# this means we will not fill the buffer of 2**14 points, and the rest of the waveform will be zero.
# it is unclear what you want - you should be clear on this, as there are many "hidden" settings in the
# asg that might enable you do do that
# if you want to switch on the analog signal
#asg.output_direct = "out1"
# Acquire and plot data
ch1, ch2 = scope.curve()
times = scope.times
plt.plot(times, ch1)
plt.show()
I know the waveform I generated is likely not what you want, but you have not really told me. The issue I a having comes from n
being less than 2**14
, i.e. not filling the entire buffer.
One way would be to stretch your waveform to fill the entire buffer (change n to 2**14 in above example). This is the best solution most of the time, as it gives you the largest interpolation grid (good phase resolution) for outputting the desired waveform.
Another option, if you really have to use 3125 or so points, is to modify the asg such that it only outputs the first 3125 points of its buffer, and then wraps back to the start. Internally, the asg has a counter of 30 bits, and at each clock cycle it adds _counter_step
to this value. It then takes the highest 14 bits of this counter as the index of your waveform to output. You can specify
_counter_wrap
where this counter will start over from zero (by default at 2**16 * 2**14 - 1
), _counter_step
(indirectly encoding your signal frequency),_sm_wrappointer
, whether after wrapping, the counter should start at zero (False), or take into account the accumulated counter offset (i.e. just subtract _counter_wrap
from the counter when its time to wrap it). This is an important distinction when _counter_step / _counter_wrap
is not integer. By default, _sm_wrappointer=True
.Thanks a lot @lneuhaus for the detailed answer!
I was able to output a custom, periodic signal of length n by setting the counter wrap accordingly:
asg._counter_wrap=n*2**16
I hope this helps other users setting up the ASG. Maybe a link to this issue in the API manual would also be useful!
I am trying to output a custom, periodic signal using the ASG. As a test, I want to output a ramp between -500 mV and 500 mV. Looping OUT1 to IN1 and running the attached test script, I get this unexpected waveform:
I have tried for 10 hours to understand asg.py, using the information from #335, but still I wasn't able to find a way to set up a custom waveform for the ASG.
Is there a bug or am I missing something?