Compare commits
6 Commits
52e560c090
...
c499090cdb
Author | SHA1 | Date |
---|---|---|
Sebastien Bourdeauducq | c499090cdb | |
Sebastien Bourdeauducq | 8fcec4b17c | |
Sebastien Bourdeauducq | 5c4f541669 | |
Sebastien Bourdeauducq | dadd09d914 | |
Sebastien Bourdeauducq | d41493934b | |
Sebastien Bourdeauducq | cd58894f3c |
|
@ -1 +0,0 @@
|
|||
bladerf.conf
|
|
@ -0,0 +1 @@
|
|||
biastee_rx on
|
4
dmi.py
4
dmi.py
|
@ -30,7 +30,7 @@ def main():
|
|||
for channel in range(2):
|
||||
sdr.setSampleRate(SoapySDR.SOAPY_SDR_RX, channel, freq_sample)
|
||||
sdr.setFrequency(SoapySDR.SOAPY_SDR_RX, channel, freq_base)
|
||||
sdr.setGain(SoapySDR.SOAPY_SDR_RX, channel, 57.0)
|
||||
sdr.setGain(SoapySDR.SOAPY_SDR_RX, channel, 55.0)
|
||||
|
||||
buf_sdr = BufferedSDR(sdr, [0, 1], block_size, 32)
|
||||
buf_sdr.start()
|
||||
|
@ -55,7 +55,7 @@ def main():
|
|||
|
||||
if stabilizer.locked():
|
||||
position = position_tracker.input(samples_ref, samples_meas)
|
||||
position_acc += np.sum(position)/len(position)
|
||||
position_acc += np.mean(position)
|
||||
if throttle == 0:
|
||||
gui.update_position(position_acc/throttle_factor)
|
||||
position_acc = 0.0
|
||||
|
|
|
@ -72,7 +72,7 @@ class MainWindow(pg.GraphicsLayoutWidget):
|
|||
|
||||
def update_position(self, position):
|
||||
self.position_history = np.roll(self.position_history, -1)
|
||||
self.position_history[-1] = position*632.816/2
|
||||
self.position_history[-1] = position*632.816/(4.0*np.pi)
|
||||
self.position.clear()
|
||||
self.position.plot(self.position_history)
|
||||
|
||||
|
|
21
noptica.py
21
noptica.py
|
@ -112,13 +112,16 @@ class Stabilizer:
|
|||
self.freq_target = freq_target
|
||||
self.cb = cb
|
||||
|
||||
self.amp_counter = 0
|
||||
self.lock_counter = 0
|
||||
self.unlock_counter = 0
|
||||
self.wiggle = 0.0
|
||||
self.tuning = 0.0
|
||||
|
||||
self.amp_threshold = 80.0
|
||||
self.k = 30.0e-6
|
||||
self.tolerance = 10e3
|
||||
self.amp_counter_threshold = 60
|
||||
self.lock_counter_threshold = 60
|
||||
self.unlock_counter_threshold = 500
|
||||
self.wiggle_amplitude = 0.15
|
||||
|
@ -132,14 +135,16 @@ class Stabilizer:
|
|||
if amplitude > self.amp_threshold:
|
||||
freq = self.freqs[i]
|
||||
delta = freq - self.freq_target
|
||||
tuning = delta*self.k
|
||||
self.amp_counter += 1
|
||||
if self.amp_counter > self.amp_counter_threshold:
|
||||
self.tuning = delta*self.k
|
||||
if abs(delta) < self.tolerance:
|
||||
success = True
|
||||
else:
|
||||
freq = None
|
||||
tuning = 0.0
|
||||
self.amp_counter = 0
|
||||
max_tuning_abs = 0.5 - self.wiggle_amplitude - 1e-9
|
||||
tuning = max(min(tuning, max_tuning_abs), -max_tuning_abs)
|
||||
self.tuning = max(min(self.tuning, max_tuning_abs), -max_tuning_abs)
|
||||
|
||||
if success:
|
||||
self.lock_counter += 1
|
||||
|
@ -151,11 +156,12 @@ class Stabilizer:
|
|||
else:
|
||||
self.unlock_counter += 1
|
||||
if not success and (self.unlock_counter > self.unlock_counter_threshold):
|
||||
print("wiggle")
|
||||
self.wiggle = self.wiggle_amplitude*np.random.uniform(-1.0, 1.0)
|
||||
print("wiggle", self.wiggle)
|
||||
self.unlock_counter = 0
|
||||
self.amp_counter = 0
|
||||
|
||||
self.cb(spectrum, freq, self.locked(), tuning + self.wiggle)
|
||||
self.cb(spectrum, freq, self.locked(), self.tuning + self.wiggle)
|
||||
|
||||
def locked(self):
|
||||
return self.lock_counter > self.lock_counter_threshold
|
||||
|
@ -178,9 +184,8 @@ class PositionTracker:
|
|||
self.last_position = 0.0
|
||||
|
||||
def input(self, ref, meas):
|
||||
demod = np.conjugate(ref)*meas
|
||||
phase = np.angle(demod)
|
||||
position = continuous_unwrap(self.last_phase, self.last_position, phase)/(2.0*np.pi)
|
||||
phase = np.angle(meas*ref.conj())
|
||||
position = continuous_unwrap(self.last_phase, self.last_position, phase)
|
||||
self.last_phase = phase[-1]
|
||||
self.last_position = position[-1]
|
||||
return position
|
||||
|
|
23
shell.nix
23
shell.nix
|
@ -16,6 +16,22 @@ let
|
|||
url = "https://www.nuand.com/fpga/v0.11.0/hostedxA4.rbf";
|
||||
sha256 = "c172e35c4a92cf1e0ca3b37347a84d8376b275ece16cb9c5142b72b82b16fe8e";
|
||||
};
|
||||
bladeRF-flash = pkgs.writeShellScriptBin "bladeRF-flash"
|
||||
# Using the bladeRF bias-tee is royally annoying. Opening the bladeRF turns it off,
|
||||
# and the API for turning it back on isn't exposed in SoapySDR. Using the configuration
|
||||
# file works, but breaks FPGA loading since bladeRF-cli then attempts to turn on the
|
||||
# bias-tee before loading the FPGA. Using the configuration file to load the FPGA
|
||||
# works the first time and then crashes until the bladeRF is unplugged and plugged back in.
|
||||
# To work around these assorted bugs, we flash the bladeRF from an empty directory where
|
||||
# bladeRF-cli won't find the configuration file, and let it boot the FPGA from its flash,
|
||||
# which seems less buggy/cumbersome than the other options.
|
||||
''
|
||||
TMPDIR=`mktemp -d`
|
||||
pushd $TMPDIR
|
||||
${pkgs.libbladeRF}/bin/bladeRF-cli -L ${bitstream}
|
||||
popd
|
||||
rmdir $TMPDIR
|
||||
'';
|
||||
sipyco = pkgs.python3Packages.buildPythonPackage rec {
|
||||
name = "sipyco";
|
||||
version = "1.1";
|
||||
|
@ -33,16 +49,11 @@ in
|
|||
buildInputs = [
|
||||
(pkgs.python3.withPackages(ps: [ps.soapysdr-with-plugins ps.scipy ps.pyserial ps.quamash ps.pyqt5 pyqtgraph-qt5 sipyco]))
|
||||
pkgs.libbladeRF pkgs.gqrx
|
||||
bladeRF-flash
|
||||
];
|
||||
dontWrapQtApps = true;
|
||||
postFixup = ''
|
||||
wrapQtApp "$out/bin/python"
|
||||
'';
|
||||
shellHook = ''
|
||||
cat > bladerf.conf << EOF
|
||||
fpga ${bitstream}
|
||||
biastee_rx on
|
||||
EOF
|
||||
'';
|
||||
QT_QPA_PLATFORM = "wayland";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue