Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into hardware-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jonschumacher committed Mar 12, 2024
2 parents dcd97dc + e9f9e37 commit fc14421
Show file tree
Hide file tree
Showing 22 changed files with 445 additions and 135 deletions.
3 changes: 3 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"

[compat]
Documenter = "1"
3 changes: 2 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ makedocs(
"FPGA Development" => "fpga.md",
"Development Tips" => "devtips.md",
#"Getting Started" => "overview.md",
]
],
warnonly = [:missing_docs]
# html_prettyurls = false, #!("local" in ARGS),
)

Expand Down
6 changes: 3 additions & 3 deletions docs/src/acquisition.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Data Acqusition
# Data Acquisition

The data acqusition of the RedPitayaDAQServer project is based on two data flows to and from the upper 128 MB of the RedPitaya memory. This memory region acts as a ring buffer for the acquired samples and can be queried by clients using SCPI commands.
The data acquisition of the RedPitayaDAQServer project is based on two data flows to and from the upper 128 MB of the RedPitaya memory. This memory region acts as a ring buffer for the acquired samples and can be queried by clients using SCPI commands.

Signal acquisition within a cluster is based on a shared clock and trigger signal distributed via cables between the RedPitayas. Once triggered, all FPGAs continuously write the samples from their ADC channel to the sample ring-buffer with each clock tick. Both ADC channels on a RedPitaya are written to the buffer at the same time. The 14-bit values of the ADCs are converted to 16-bit signed integer samples and then concatenated into one 32-bit value, which is then written to the buffer. The sampling rate of the system can be adjusted by setting a decimation parameter and the decimation itself is realized with a CIC filter.

Expand Down Expand Up @@ -43,4 +43,4 @@ At this sampling rate a single RedPitaya produces new samples at a data rate of
|16|7.81|31.25|250|4.29s|
|8|15.63|62.5|500|2.15s|

The table only refers to the data rate of new samples being produced. The data rate of samples being transmitted to a client can differ greatly depending on how the client queries and processes the samples and the available network bandwidth and usage. At the higher sampling rates it is recommended to have client threads that exclusively receive samples and perform any computation on samples in different threads to maximise the transmission speed, as a server can only transmit data at a rate of just above 500 Mbit/s. This exceeds the highest supported sampling rate by only a few Mbit/s and a client with frequency interruptions of its sample reception might not be able to keep up with the sampling rate.
The table only refers to the data rate of new samples being produced. The data rate of samples being transmitted to a client can differ greatly depending on how the client queries and processes the samples and the available network bandwidth and usage. At the higher sampling rates it is recommended to have client threads that exclusively receive samples and perform any computation on samples in different threads to maximise the transmission speed, as a server can only transmit data at a rate of just above 500 Mbit/s. This exceeds the highest supported sampling rate by only a few Mbit/s and a client with frequency interruptions of its sample reception might not be able to keep up with the sampling rate.
31 changes: 22 additions & 9 deletions docs/src/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This page contains documentation of the public API of the Julia client. In the Julia
REPL one can access this documentation by entering the help mode with `?` and
then writing the function for which the documentation should be shown.

## Connection and Communication
```@docs
RedPitayaDAQServer.RedPitaya
Expand Down Expand Up @@ -40,6 +41,7 @@ RedPitayaDAQServer.calibADCOffset
RedPitayaDAQServer.calibADCOffset!
RedPitayaDAQServer.calibADCScale
RedPitayaDAQServer.calibADCScale!
RedPitayaDAQServer.updateCalib!
```
## DAC Configuration
```@docs
Expand All @@ -61,12 +63,12 @@ RedPitayaDAQServer.samplesPerStep!
RedPitayaDAQServer.stepsPerFrame!
RedPitayaDAQServer.clearSequence!
RedPitayaDAQServer.sequence!
RedPitayaDAQServer.length(::AbstractSequence)
RedPitayaDAQServer.start
RedPitayaDAQServer.calibDACOffset
RedPitayaDAQServer.calibDACOffset!
RedPitayaDAQServer.calibDACScale
RedPitayaDAQServer.calibDACScale!
RedPitayaDAQServer.calibDACUpperLimit!
RedPitayaDAQServer.calibDACLowerLimit!
```
## Measurement and Transmission
```@docs
Expand All @@ -79,11 +81,22 @@ RedPitayaDAQServer.SampleChunk
RedPitayaDAQServer.PerformanceData
RedPitayaDAQServer.readSamples
RedPitayaDAQServer.readFrames
RedPitayaDAQServer.convertSamplesToFrames
RedPitayaDAQServer.readPeriods
RedPitayaDAQServer.convertSamplesToFrames(::Union{RedPitaya, RedPitayaCluster, RedPitayaClusterView}, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any)
RedPitayaDAQServer.convertSamplesToPeriods!(::Union{RedPitaya, RedPitayaCluster, RedPitayaClusterView}, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any)
```
## Slow IO
```@autodocs
Modules = [RedPitayaDAQServer]
Pages = ["SlowIO.jl"]
```
## EEPROM and Calibration
```@autodocs
Modules = [RedPitayaDAQServer]
Pages = ["EEPROM.jl"]
```
## Counter Trigger
```@autodocs
Modules = [RedPitayaDAQServer]
Pages = ["CounterTrigger.jl"]
```
## Utility
```@docs
RedPitayaDAQServer.listReleaseTags
RedPitayaDAQServer.latestReleaseTags
RedPitayaDAQServer.update!
```
4 changes: 2 additions & 2 deletions docs/src/generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ Comparable to the sample transmission of the acquisition, this updating of the L
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.

## Calibration
Similar to the signal acqusition, 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.
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.

Thus the total signal can be described as:
```math
S_i''(t) = c_{i, scale} S_i'(t) + c_{i, offset}
```
```
4 changes: 2 additions & 2 deletions docs/src/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ To finish installing the RedPitaya, simply unzip one of the releases and copy th

When the RedPitaya is now booted, the server should start. One can then use a client to connect, at which point the FPGA image is loaded.

The client library provided with the project is not an executable program, but it can be used to implement one. The library encapsulates the communication with the server and implements various optimizations. As the communication with the server is language agnostic one could therefore implement their own client in a different language. The Julia reference client library found in `src/client/julia`, the [SCPI commands](scpi.md) and the sections on the signal [acquisition](acqusition.md) and [generation](generation.md) are starting points for such a custom client.
The client library provided with the project is not an executable program, but it can be used to implement one. The library encapsulates the communication with the server and implements various optimizations. As the communication with the server is language agnostic one could therefore implement their own client in a different language. The Julia reference client library found in `src/client/julia`, the [SCPI commands](scpi.md) and the sections on the signal [acquisition](acquisition.md) and [generation](generation.md) are starting points for such a custom client.

## Julia Client
To use the provided Julia client library you need to install RedPitayaDAQServer Julia package within Julia. To this end
Expand Down Expand Up @@ -148,4 +148,4 @@ dev RedPitayaDAQServer
```
in the package mode `]`.

This installs the package in development mode and puts the files into `~/.julia/dev/RedPitayaDAQServer/`. There you can the also modify the files, which is handy when trying out the examples. You need to manually `git pull` if you want to get updates, i.e. Julia will not update developed packages automatically.
This installs the package in development mode and puts the files into `~/.julia/dev/RedPitayaDAQServer/`. There you can the also modify the files, which is handy when trying out the examples. You need to manually `git pull` if you want to get updates, i.e. Julia will not update developed packages automatically.
2 changes: 1 addition & 1 deletion docs/src/scpi.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ After each SCPI command the server replies with `true` or `false` on the command


## Sequence Configuration
The server maintains three acqusition sequences. When the server is in the`CONFIGURATION` mode a client can configure a set of three sequences. If the current configured sequences fits the desired signal, a client can intstruct the server to set the sequences. This moves the configuration sequences to the acquisition sequences and writes the first values to the FPGA buffer.
The server maintains three acquisition sequences. When the server is in the`CONFIGURATION` mode a client can configure a set of three sequences. If the current configured sequences fits the desired signal, a client can intstruct the server to set the sequences. This moves the configuration sequences to the acquisition sequences and writes the first values to the FPGA buffer.

During an active trigger the buffer is periodically updated by the server. If the server recognizes the end of a sequence, it sets the amplitudes of the waveform components to 0.

Expand Down
8 changes: 7 additions & 1 deletion src/client/julia/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "RedPitayaDAQServer"
uuid = "c544963a-496b-56d4-a5fe-f99a3f174c8f"
authors = ["Tobias Knopp <[email protected]>"]
version = "0.6.0"
version = "0.8.0"

[deps]
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
Expand All @@ -11,7 +11,13 @@ Sockets = "6462fe0b-24de-5631-8697-dd941f90decc"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[compat]
Aqua = "0.8"
DocStringExtensions = "0.8, 0.9"
LinearAlgebra = "1"
Random = "1"
Statistics = "1"
Sockets = "1"
Test = "1"
julia = "1.7"

[extras]
Expand Down
3 changes: 3 additions & 0 deletions src/client/julia/src/ADC.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ function RPStatus(statusRaw::Integer)
)
end

"""
Holds the performance data that is used for monitoring.
"""
struct PerformanceData
wpRead::UInt64
adc::ADCPerformanceData
Expand Down
120 changes: 40 additions & 80 deletions src/client/julia/src/Acquisition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -268,25 +268,13 @@ function readFrames(
return data
end

function convertSamplesToFrames(
rpu::Union{RedPitaya, RedPitayaCluster, RedPitayaClusterView},
samples,
numChan,
numSampPerPeriod,
numPeriods,
numFrames,
numBlockAverages = 1,
numPeriodsPerPatch = 1,
)
frames = convertSamplesToFrames(
samples,
numChan,
numSampPerPeriod,
numPeriods,
numFrames,
numBlockAverages,
numPeriodsPerPatch,
)
"""
Converts a given set of samples to frames.
See [`readFrames`](@ref)
"""
function convertSamplesToFrames(rpu::Union{RedPitaya, RedPitayaCluster, RedPitayaClusterView}, samples, numChan, numSampPerPeriod, numPeriods, numFrames, numBlockAverages=1, numPeriodsPerPatch=1)
frames = convertSamplesToFrames(samples, numChan, numSampPerPeriod, numPeriods, numFrames, numBlockAverages, numPeriodsPerPatch)
calibs = [x.calib for x rpu]
calib = hcat(calibs...)
for d 1:size(frames, 2)
Expand All @@ -296,16 +284,13 @@ function convertSamplesToFrames(
return frames
end

function convertSamplesToFrames(
samples,
numChan,
numSampPerPeriod,
numPeriods,
numFrames,
numBlockAverages = 1,
numPeriodsPerPatch = 1,
)
if rem(numSampPerPeriod, numBlockAverages) != 0
"""
Converts a given set of samples to frames.
See [`readFrames`](@ref)
"""
function convertSamplesToFrames(samples, numChan, numSampPerPeriod, numPeriods, numFrames, numBlockAverages=1, numPeriodsPerPatch=1)
if rem(numSampPerPeriod,numBlockAverages) != 0
error("block averages has to be a divider of numSampPerPeriod")
end
numTrueSampPerPeriod = div(numSampPerPeriod, numBlockAverages * numPeriodsPerPatch)
Expand All @@ -324,29 +309,13 @@ function convertSamplesToFrames(
return frames
end

function convertSamplesToFrames!(
rpu::Union{RedPitaya, RedPitayaCluster, RedPitayaClusterView},
samples,
frames,
numChan,
numSampPerPeriod,
numPeriods,
numFrames,
numTrueSampPerPeriod,
numBlockAverages = 1,
numPeriodsPerPatch = 1,
)
convertSamplesToFrames!(
samples,
frames,
numChan,
numSampPerPeriod,
numPeriods,
numFrames,
numTrueSampPerPeriod,
numBlockAverages,
numPeriodsPerPatch,
)
"""
Converts a given set of samples to frames in-place.
See [`readFrames`](@ref)
"""
function convertSamplesToFrames!(rpu::Union{RedPitaya, RedPitayaCluster, RedPitayaClusterView}, samples, frames, numChan, numSampPerPeriod, numPeriods, numFrames, numTrueSampPerPeriod, numBlockAverages=1, numPeriodsPerPatch=1)
convertSamplesToFrames!(samples, frames, numChan, numSampPerPeriod, numPeriods, numFrames, numTrueSampPerPeriod, numBlockAverages, numPeriodsPerPatch)
calibs = [x.calib for x rpu]
calib = hcat(calibs...)
for d 1:size(frames, 2)
Expand All @@ -355,17 +324,12 @@ function convertSamplesToFrames!(
end
end

function convertSamplesToFrames!(
samples,
frames,
numChan,
numSampPerPeriod,
numPeriods,
numFrames,
numTrueSampPerPeriod,
numBlockAverages = 1,
numPeriodsPerPatch = 1,
)
"""
Converts a given set of samples to frames in-place.
See [`readFrames`](@ref)
"""
function convertSamplesToFrames!(samples, frames, numChan, numSampPerPeriod, numPeriods, numFrames, numTrueSampPerPeriod, numBlockAverages=1, numPeriodsPerPatch=1)
temp = reshape(samples, numChan, numSampPerPeriod, numPeriods, numFrames)
for d 1:div(numChan, 2)
u = temp[(2 * d - 1):(2 * d), :, :, :]
Expand Down Expand Up @@ -440,15 +404,12 @@ function readPeriods(
return data
end

function convertSamplesToPeriods!(
rpu::Union{RedPitaya, RedPitayaCluster, RedPitayaClusterView},
samples,
periods,
numChan,
numSampPerPeriod,
numPeriods,
numBlockAverages = 1,
)
"""
Converts a given set of samples to periods in-place.
See [`readPeriods`](@ref)
"""
function convertSamplesToPeriods!(rpu::Union{RedPitaya, RedPitayaCluster, RedPitayaClusterView}, samples, periods, numChan, numSampPerPeriod, numPeriods, numBlockAverages=1)
convertSamplesToPeriods!(samples, periods, numChan, numSampPerPeriod, numPeriods, numBlockAverages)
calibs = [x.calib for x rpu]
calib = hcat(calibs...)
Expand All @@ -458,14 +419,13 @@ function convertSamplesToPeriods!(
end
return periods
end
function convertSamplesToPeriods!(
samples,
periods,
numChan,
numSampPerPeriod,
numPeriods,
numBlockAverages = 1,
)

"""
Converts a given set of samples to periods in-place.
See [`readPeriods`](@ref)
"""
function convertSamplesToPeriods!(samples, periods, numChan, numSampPerPeriod, numPeriods, numBlockAverages=1)
temp = reshape(samples, numChan, numSampPerPeriod, numPeriods)
for d 1:div(numChan, 2)
u = temp[(2 * d - 1):(2 * d), :, :]
Expand Down
Loading

0 comments on commit fc14421

Please sign in to comment.