vna_capture() working through class
This commit is contained in:
parent
a20217967f
commit
7e0df9e643
|
@ -18,6 +18,20 @@ dir_ = Path(__file__).parent
|
||||||
|
|
||||||
|
|
||||||
# %% connection
|
# %% connection
|
||||||
|
|
||||||
|
|
||||||
|
def generate_tone(f: float, fs: float, N: int = 1024, scale: int = 2**14):
|
||||||
|
fs = int(fs)
|
||||||
|
fc = int(f / (fs / N)) * (fs / N)
|
||||||
|
ts = 1 / float(fs)
|
||||||
|
t = np.arange(0, N * ts, ts)
|
||||||
|
i = np.cos(2 * np.pi * t * fc) * scale
|
||||||
|
q = np.sin(2 * np.pi * t * fc) * scale
|
||||||
|
iq = i + 1j * q
|
||||||
|
|
||||||
|
return iq
|
||||||
|
|
||||||
|
|
||||||
class Charon:
|
class Charon:
|
||||||
FREQUENCY_OFFSET = 1e6
|
FREQUENCY_OFFSET = 1e6
|
||||||
|
|
||||||
|
@ -58,19 +72,19 @@ class Charon:
|
||||||
self.sdr.loopback = 0
|
self.sdr.loopback = 0
|
||||||
self.sdr.gain_control_mode_chan0 = "manual"
|
self.sdr.gain_control_mode_chan0 = "manual"
|
||||||
self.sdr.gain_control_mode_chan1 = "manual"
|
self.sdr.gain_control_mode_chan1 = "manual"
|
||||||
self.sdr.rx_hardwaregain_chan0 = 40
|
self.sdr.rx_hardwaregain_chan0 = 10
|
||||||
self.sdr.rx_hardwaregain_chan1 = 40
|
self.sdr.rx_hardwaregain_chan1 = 10
|
||||||
self.sdr.tx_hardwaregain_chan0 = -10
|
self.sdr.tx_hardwaregain_chan0 = -10
|
||||||
|
|
||||||
# switch control
|
# # switch control
|
||||||
ctx = iio.Context(uri)
|
# ctx = iio.Context(uri)
|
||||||
self.ctrl = ctx.find_device("ad9361-phy")
|
# self.ctrl = ctx.find_device("ad9361-phy")
|
||||||
# raw ad9361 register accesss:
|
# # raw ad9361 register accesss:
|
||||||
# https://ez.analog.com/linux-software-drivers/f/q-a/120853/control-fmcomms3-s-gpo-with-python
|
# # https://ez.analog.com/linux-software-drivers/f/q-a/120853/control-fmcomms3-s-gpo-with-python
|
||||||
# https://www.analog.com/media/cn/technical-documentation/user-guides/ad9364_register_map_reference_manual_ug-672.pdf
|
# # https://www.analog.com/media/cn/technical-documentation/user-guides/ad9364_register_map_reference_manual_ug-672.pdf
|
||||||
self.ctrl.reg_write(0x26, 0x90) # bit 7: AuxDAC Manual, bit 4: GPO Manual
|
# self.ctrl.reg_write(0x26, 0x90) # bit 7: AuxDAC Manual, bit 4: GPO Manual
|
||||||
self._set_gpo(self.ports[0] - 1)
|
# self._set_gpo(self.ports[0] - 1)
|
||||||
# TODO: init AuxDAC
|
# # TODO: init AuxDAC
|
||||||
|
|
||||||
def get_config(self) -> Dict[str, Any]:
|
def get_config(self) -> Dict[str, Any]:
|
||||||
config = dict()
|
config = dict()
|
||||||
|
@ -119,17 +133,6 @@ class Charon:
|
||||||
# tx_gain = pout.coords["tx_gain"][tx_gain_idx]
|
# tx_gain = pout.coords["tx_gain"][tx_gain_idx]
|
||||||
self.sdr.tx_hardwaregain_chan0 = float(tx_gain)
|
self.sdr.tx_hardwaregain_chan0 = float(tx_gain)
|
||||||
|
|
||||||
def generate_tone(self, f: float, fs: float, N: int = 1024, scale: int = 2**14):
|
|
||||||
fs = int(fs)
|
|
||||||
fc = int(f / (fs / N)) * (fs / N)
|
|
||||||
ts = 1 / float(fs)
|
|
||||||
t = np.arange(0, N * ts, ts)
|
|
||||||
i = np.cos(2 * np.pi * t * fc) * scale
|
|
||||||
q = np.sin(2 * np.pi * t * fc) * scale
|
|
||||||
iq = i + 1j * q
|
|
||||||
|
|
||||||
return iq
|
|
||||||
|
|
||||||
def set_output(self, frequency: float, power: float):
|
def set_output(self, frequency: float, power: float):
|
||||||
# TODO: switch to DDS in Pluto
|
# TODO: switch to DDS in Pluto
|
||||||
|
|
||||||
|
@ -137,7 +140,7 @@ class Charon:
|
||||||
self.set_output_power(power)
|
self.set_output_power(power)
|
||||||
self.sdr.tx_lo = int(frequency - self.FREQUENCY_OFFSET)
|
self.sdr.tx_lo = int(frequency - self.FREQUENCY_OFFSET)
|
||||||
self.sdr.tx_cyclic_buffer = True
|
self.sdr.tx_cyclic_buffer = True
|
||||||
# self.sdr.tx(self.generate_tone(f=self.FREQUENCY_OFFSET, fs=self.sdr.sample_rate))
|
# self.sdr.tx(generate_tone(f=self.FREQUENCY_OFFSET, fs=self.sdr.sample_rate))
|
||||||
self.sdr.dds_single_tone(self.FREQUENCY_OFFSET, scale=0.9, channel=0)
|
self.sdr.dds_single_tone(self.FREQUENCY_OFFSET, scale=0.9, channel=0)
|
||||||
|
|
||||||
def _rx(self, count: int = 1, fc: float | None = None) -> npt.ArrayLike:
|
def _rx(self, count: int = 1, fc: float | None = None) -> npt.ArrayLike:
|
||||||
|
@ -158,7 +161,7 @@ class Charon:
|
||||||
self.set_output(frequency=frequency, power=-5)
|
self.set_output(frequency=frequency, power=-5)
|
||||||
|
|
||||||
data = self._rx(1, fc=frequency - self.FREQUENCY_OFFSET)
|
data = self._rx(1, fc=frequency - self.FREQUENCY_OFFSET)
|
||||||
ddc_tone = self.generate_tone(f=-self.FREQUENCY_OFFSET, fs=self.sdr.sample_rate, scale=1)
|
ddc_tone = generate_tone(f=-self.FREQUENCY_OFFSET, fs=self.sdr.sample_rate, scale=1)
|
||||||
ddc_data = data * ddc_tone
|
ddc_data = data * ddc_tone
|
||||||
|
|
||||||
ddc_rel = ddc_data[1] / ddc_data[0]
|
ddc_rel = ddc_data[1] / ddc_data[0]
|
||||||
|
@ -202,14 +205,36 @@ class Charon:
|
||||||
s.loc[dict(frequency=frequency)] = self.get_b_over_a(frequency=frequency)
|
s.loc[dict(frequency=frequency)] = self.get_b_over_a(frequency=frequency)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def vna_capture(self, frequency: npt.ArrayLike):
|
||||||
|
s = xr.DataArray(
|
||||||
|
np.empty(len(frequency), dtype=np.complex128),
|
||||||
|
dims=["frequency"],
|
||||||
|
coords=dict(
|
||||||
|
frequency=frequency,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
for freq in s.frequency.data:
|
||||||
|
self.set_output(frequency=freq, power=-5)
|
||||||
|
self.sdr.rx_destroy_buffer()
|
||||||
|
self.sdr.rx_lo = int(freq)
|
||||||
|
self.sdr.rx_enabled_channels = [0, 1]
|
||||||
|
self.sdr.gain_control_mode_chan0 = "manual"
|
||||||
|
self.sdr.gain_control_mode_chan1 = "manual"
|
||||||
|
self.sdr.rx_hardwaregain_chan0 = 40
|
||||||
|
self.sdr.rx_hardwaregain_chan1 = 40
|
||||||
|
rx = self.sdr.rx()
|
||||||
|
s.loc[dict(frequency=freq)] = np.mean(rx[1] / rx[0])
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
# %%
|
# %%
|
||||||
sdr = Charon("ip:192.168.3.1", frequency=np.linspace(1e9, 1.1e9, 11))
|
sdr = Charon("ip:192.168.3.1", frequency=np.linspace(1e9, 1.1e9, 11))
|
||||||
|
|
||||||
# %% initialization
|
# %% initialization
|
||||||
config = sdr.get_config()
|
config = sdr.get_config()
|
||||||
print(sdr.ctrl.debug_attrs["adi,rx-rf-port-input-select"].value)
|
# print(sdr.ctrl.debug_attrs["adi,rx-rf-port-input-select"].value)
|
||||||
print(sdr.ctrl.debug_attrs["adi,tx-rf-port-input-select"].value)
|
# print(sdr.ctrl.debug_attrs["adi,tx-rf-port-input-select"].value)
|
||||||
config
|
config
|
||||||
|
|
||||||
# %% generate tone
|
# %% generate tone
|
||||||
|
@ -264,31 +289,7 @@ plt.show()
|
||||||
|
|
||||||
|
|
||||||
# %%
|
# %%
|
||||||
def vna_capture(frequency: npt.ArrayLike):
|
s = sdr.vna_capture(frequency=np.linspace(70e6, 200e6, 101))
|
||||||
s = xr.DataArray(
|
|
||||||
np.empty(len(frequency), dtype=np.complex128),
|
|
||||||
dims=["frequency"],
|
|
||||||
coords=dict(
|
|
||||||
frequency=frequency,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
for freq in s.frequency.data:
|
|
||||||
set_output(frequency=freq, power=-5)
|
|
||||||
sdr.rx_destroy_buffer()
|
|
||||||
sdr.rx_lo = int(freq)
|
|
||||||
sdr.rx_enabled_channels = [0, 1]
|
|
||||||
sdr.gain_control_mode_chan0 = "manual"
|
|
||||||
sdr.gain_control_mode_chan1 = "manual"
|
|
||||||
sdr.rx_hardwaregain_chan0 = 40
|
|
||||||
sdr.rx_hardwaregain_chan1 = 40
|
|
||||||
rx = sdr.rx()
|
|
||||||
s.loc[dict(frequency=freq)] = np.mean(rx[1] / rx[0])
|
|
||||||
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
# %%
|
|
||||||
s = vna_capture(frequency=np.linspace(70e6, 200e6, 101))
|
|
||||||
|
|
||||||
# %% Plot Logmag
|
# %% Plot Logmag
|
||||||
fig, axs = plt.subplots(2, 1, sharex=True, tight_layout=True)
|
fig, axs = plt.subplots(2, 1, sharex=True, tight_layout=True)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user