diff --git a/docs/make.jl b/docs/make.jl index 085f2756..5e4a0765 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -23,7 +23,8 @@ makedocs( "Sequence Ramping" => "examples/seqRamping.md", "Cluster" => "examples/cluster.md", "Batch" => "examples/batch.md", - "Continous Signal Acquisition" => "examples/producerConsumer.md"], + "Continous Signal Acquisition" => "examples/producerConsumer.md", + "Resync" => "examples/resync.md",], "FPGA Development" => "fpga.md", "Development Tips" => "devtips.md", #"Getting Started" => "overview.md", diff --git a/docs/src/assets/resync.png b/docs/src/assets/resync.png new file mode 100644 index 00000000..85296d14 Binary files /dev/null and b/docs/src/assets/resync.png differ diff --git a/docs/src/examples/resync.md b/docs/src/examples/resync.md new file mode 100644 index 00000000..63aa636f --- /dev/null +++ b/docs/src/examples/resync.md @@ -0,0 +1,21 @@ +# Resync Example + +In this example we add a resync signal to a [sequence](sequence.md) to create a signal that resynchronizes phase and frequency of the DACs after every frame. This can be used to change the frequency and phase of a signal during measurement. While the resynchronization is synchronous due to the sequences, the actual new frequency and phase information is asynchronous as they are transmitted via SCPI. + +The example constructs a sequence with no offset and the very last step has the resync flag enabled. Note that during the resync-step the DAC outputs zero. + +## Julia Client + +This and all other examples are located in the ```examples``` [directory](https://github.com/tknopp/RedPitayaDAQServer/tree/master/src/examples/julia) + +````@eval +# Adapted from https://github.com/JuliaDocs/Documenter.jl/issues/499 +using Markdown +Markdown.parse(""" +```julia +$(open(f->read(f, String), "../../../src/examples/julia/resync.jl")) +``` +""") +```` + +![Resync Example Results](../assets/resync.png) diff --git a/docs/src/generation.md b/docs/src/generation.md index d57cfce4..e9b785a4 100644 --- a/docs/src/generation.md +++ b/docs/src/generation.md @@ -25,7 +25,7 @@ As the LUT used by the FPGA image is small in comparison with the main memory an Comparable to the sample transmission of the acquisition, this updating of the LUT is also a process with timing uncertainty as it is affected by the scheduling and execution of the RedPitayas CPU. While during the sample transmission samples could be lost because they were overwritten, in the signal generation wrong signals could be output because the server was too slow in updating the values. Here, the server tracks similar performance metrics and also features a status flag `lostSteps` for exactly this case. In its current implementation a safe step rate is at 12 kHz. -Sequences and their steps also have additional features. A step can be marked such that during its duration the signal is set to 0. Furthermore, a step can be marked such that it triggers the ramp down. To make this easier to manage the server actually manages three sequences, that can be set individually: A ramp up, regular and ramp down sequence. The ramp up sequence is moved to the FPGA LUT at the acquisition start, followed by the regular sequence. Afterwards the ramp down sequence is started and during its execution the ramp down flag is set. +Sequences and their steps also have additional features. A step can be marked such that during its duration the signal is set to 0. Furthermore, a step can be marked such that it triggers the ramp down. To make this easier to manage the server actually manages three sequences, that can be set individually: A ramp up, regular and ramp down sequence. The ramp up sequence is moved to the FPGA LUT at the acquisition start, followed by the regular sequence. Afterwards the ramp down sequence is started and during its execution the ramp down flag is set. Steps can also be marked to resync the fast DACs. During a resync, the signals are set to 0 and afterwards start again with their set phase and frequency. This can be used to change frequency and phase during measurements and s.t. the new phase and frequency is synchronous to the steps. ## Calibration Similar to the signal acquisition, there are also calibration scale ``c_{i, scale}`` and offset ``c_{i, offset}`` values for the signal generation. These are stored in the EEPROM of the RedPitaya and can be updated by a client. The calibration values are always applied, even when the master trigger is off. diff --git a/docs/src/scpi.md b/docs/src/scpi.md index 9af44dbd..3ca6c1d2 100644 --- a/docs/src/scpi.md +++ b/docs/src/scpi.md @@ -53,6 +53,7 @@ During an active trigger the buffer is periodically updated by the server. If th | RP:DAC:SEQ:CHan? | | Return the number of sequence channel | | | | RP:DAC:SEQ:LUT | steps, repetitions | Instruct the server to receive a LUT over the data socket | C | RP:DAC:SEQ:LUT 10,2 | | RP:DAC:SEQ:LUT:ENaBle | | Instruct the server to receive an enable LUT over the data socket of the same shape as the regular LUT| C | | +| RP:DAC:SEQ:LUT:ReSYNC | | Instruct the server to receive a resync LUT over the data socket of the same shape as the regular LUT| C | | | RP:DAC:SEQ:LUT:UP | steps, repetitions | Instruct the server to receive a ramp up LUT over the data socket | C | | | RP:DAC:SEQ:LUT:DOWN | steps, repetitions | Instruct the server to receive a ramp down LUT over the data socket | C | | | RP:DAC:SEQ:CLEAR | | Clear the set sequence values from the FPGA buffer | C | | diff --git a/src/examples/julia/resync.jl b/src/examples/julia/resync.jl new file mode 100644 index 00000000..9759d411 --- /dev/null +++ b/src/examples/julia/resync.jl @@ -0,0 +1,78 @@ +using RedPitayaDAQServer +using CairoMakie + +# obtain the URL of the RedPitaya +include("config.jl") + +rp = RedPitaya(URLs[1]) +serverMode!(rp, CONFIGURATION) + +dec = 32 +modulus = 124800 +base_frequency = 125000000 +periods_per_step = 5 +samples_per_period = div(modulus, dec) +periods_per_frame = 50 +frame_period = dec*samples_per_period*periods_per_frame / base_frequency +steps_per_frame = div(50, periods_per_step) + +decimation!(rp, dec) +samplesPerPeriod!(rp, samples_per_period) +periodsPerFrame!(rp, periods_per_frame) + +for i in 1:2 + frequencyDAC!(rp, i, 1, base_frequency / modulus) + signalTypeDAC!(rp, i, 1, "SINE") + amplitudeDAC!(rp, i, 1, 0.2) + phaseDAC!(rp, i, 1, 0) +end +triggerMode!(rp, INTERNAL) + +# Sequence Configuration +clearSequence!(rp) +stepsPerFrame!(rp, steps_per_frame) +seqChan!(rp, 2) +lut = reshape(fill(0.0f0, steps_per_frame), 1, :) +lut = repeat(lut, outer = 2) +enable = collect(fill(true, steps_per_frame)) +enable = reshape(enable, 1, :) +enable = repeat(enable, outer = 2) +# In the last step of each frame we resync the DACs +resync = vcat(fill(false, steps_per_frame - 1), [true]) +resync = reshape(resync, 1, :) +resync = repeat(resync, outer = 2) +seq = SimpleSequence(lut, 2, enable, resync) +sequence!(rp, seq) + +samples_per_frame = samples_per_period * periods_per_frame +target = samples_per_frame * 0.3 # After a third of a frame we want to switch frequency + +serverMode!(rp, ACQUISITION) +masterTrigger!(rp, true) + +# Wait until we reach the target sample +curr = currentWP(rp) +while curr < target + # NOP + global curr = currentWP(rp) + sleep(0.01) +end + +# Update the phase and frequency of the second channel +frequencyDAC!(rp, 2, 1, base_frequency / (2*modulus)) +phaseDAC!(rp, 2, 1, pi) + +data = readFrames(rp, 0, 2) + +masterTrigger!(rp, false) +serverMode!(rp, CONFIGURATION) + + +fig = Figure() +lines(fig[1, 1], vec(data[:, 2, :, 1]), axis = (ylabel = "First Frame", title = "All Periods")) +lines(fig[1, 2], vec(data[:, 2, 1:5, 1]), axis = (ylabel = "First Frame", title = "First Periods")) +lines(fig[2, 1], vec(data[:, 2, :, 2]), axis = (ylabel = "Second Frame",)) +lines(fig[2, 2], vec(data[:, 2, 1:5, 2]), axis = (ylabel = "Second Frame",)) + +save(joinpath(@__DIR__(), "images", "resync.png"), fig) +fig \ No newline at end of file