JuliaComputing / xtrx_julia

XTRX LiteX/LitePCIe based design for Julia Computing
BSD 2-Clause "Simplified" License
1 stars 0 forks source link

Continue work on high-level API #89

Closed maleadt closed 1 year ago

maleadt commented 2 years ago

Together with https://github.com/JuliaTelecom/SoapySDR.jl/pull/78, the following seems to make sense now (at least when inspecting the data we get back on the loopback; didn't test actualy Tx/Rx):

simple_loopback_multichannel.jl

ENV["SOAPY_SDR_LOG_LEVEL"] = "DEBUG"

using SoapySDR, Printf, Unitful

#SoapySDR.register_log_handler()

function loopback_test(num_channels=2)
    # open the first device
    devs = Devices(parse(KWArgs, "driver=XTRX"))
    dev = Device(devs[1])

    # get the RX and TX channels
    chan_rx = SoapySDR.Channel[]
    chan_tx = SoapySDR.Channel[]
    for i in 1:num_channels
        push!(chan_rx, dev.rx[i])
        push!(chan_tx, dev.tx[i])
    end

    # enable a loopback
    SoapySDR.SoapySDRDevice_writeSetting(dev, "LOOPBACK_ENABLE", "TRUE")

    # open RX and TX streams
    format = Complex{Int16} #chan_rx.native_stream_format
    stream_rx = SoapySDR.Stream(format, chan_rx)
    stream_tx = SoapySDR.Stream(format, chan_tx)

    # properties that matter for the buffers we'll be using
    mtu = Int(stream_tx.mtu)

    try
        wr_cnt = 0
        rd_cnt = 0
        should_transmit() = wr_cnt < 999
        should_receive() = rd_cnt < 3000
        # NOTE: we read more buffers in case there's delay between TX and RX

        SoapySDR.activate!(stream_rx)
        SoapySDR.activate!(stream_tx)

        while should_transmit() || should_receive()
            if should_transmit()
                buffs = []
                for i in 1:num_channels
                    buf = Vector{format}(undef, mtu)
                    buf .= (2*num_channels*wr_cnt+1+(i-1)*num_channels)+(2*num_channels*wr_cnt+2+(i-1)*num_channels)im
                    push!(buffs, buf)
                end
                write(stream_tx, tuple(buffs...))
                wr_cnt += 1
            end

            if should_receive()
                buffs = []
                for i in 1:num_channels
                    buf = Vector{format}(undef, mtu)
                    push!(buffs, buf)
                end
                read!(stream_rx, tuple(buffs...); timeout=5u"s")
                rd_cnt += 1

                if rd_cnt % 32 == 0
                    println()
                end
                @printf("%3d ", real(buffs[1][1]))
            end
        end
        println()
    finally
        SoapySDR.deactivate!(stream_tx)
        SoapySDR.deactivate!(stream_rx)

        # close everything
        finalize.([stream_rx, stream_tx])
        finalize(dev)
    end
end

isinteractive() || loopback_test()
isinteractive() || loopback_test()
sjkelly commented 1 year ago

Let's not merge this yet. I would like to port over test_pattern so we can validate buffer ordering, but there seem to still be some issues I need to qualify.

sjkelly commented 1 year ago

I guess we ought to sign extend in here as well while we are at it for simplicity. We can keep the old behavior by specify an unsigned stream type.

staticfloat commented 1 year ago

I think if we are going to sign-extend it should be in the FPGA. If we ask for 12-bit samples, the FPGA should not sign-extend (obviously) but this is, IMO, a classic case of something good to do in the FPGA.

sjkelly commented 1 year ago

So there is a conflation here between the number of samples for the DMA API and the number of samples in the stream API. The requested samples are per channel in the stream API. This is causing some issues in my validation when interfacing with the higher level Soapy layers that rely on this to e.g. collect 1e6 samples in a single array.

sjkelly commented 1 year ago

Okay this should be good to go. Note that the acquire buffer section will need some more work, so I removed it for now: https://github.com/JuliaComputing/xtrx_julia/pull/89/commits/b5ed3376d2c8b3fd61bca3eb2b42b4058f2d1c8a

image

sjkelly commented 1 year ago

I am merging this since I need it for several other tests and bringups, and as it stand this PR only adds the high level API. The change in https://github.com/JuliaComputing/xtrx_julia/commit/b5ed3376d2c8b3fd61bca3eb2b42b4058f2d1c8a is related to the buffer handling, which we will need to revisit with synchronization as well. We can move that to a separate PR.