Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slider etc #17

Merged
merged 2 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/misc/io_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def __initIOHandlers(cls):
psplot = selectPlotType(p, processor, cls.fileInfo['bitsPerSample'][1], cls.correctIq)
plotter = Process(target=psplot.processData,
args=(cls.isDead, buffer, cls.fs),
kwargs={'offset': cls.center, 'iq': cls.correctIq},
daemon=True)
plotUuid = IOArgs.addConsumer(plotter, uuid=psplot.uuid)
plotter.name = "Plotter-" + str(plotUuid)
Expand Down
8 changes: 1 addition & 7 deletions src/plots/qt_spectrum_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@
import numpy as np
from scipy import fft

from dsp.iq_correction import IQCorrection


class AbstractSpectrumAnalyzer(ABC):
def __init__(self, fs: int, iq: bool = False, *args, **kwargs):
def __init__(self, fs: int, *args, **kwargs):

import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtWidgets
Expand All @@ -37,7 +35,6 @@ def __init__(self, fs: int, iq: bool = False, *args, **kwargs):
self.widget = pg.PlotWidget(name="spectrum")
self.item = self.widget.getPlotItem()
self.fs = fs
self.iqCorrector = IQCorrection(fs) if iq else None

self.item.setXRange(-self._nyquistFs, self._nyquistFs, padding=0)
self.app.quitOnLastWindowClosed()
Expand Down Expand Up @@ -67,9 +64,6 @@ def update(self):
if data is None or not len(data):
raise KeyboardInterrupt

if self.iqCorrector is not None:
data = self.iqCorrector.correctIq(data)

fftData = fft.fft(data, norm='forward')
fftData = fft.fftshift(fftData)
amps = np.abs(fftData)
Expand Down
22 changes: 17 additions & 5 deletions src/plots/spectrum_analyzer_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,41 @@
from multiprocessing import Queue, Value
from uuid import uuid4

from dsp.iq_correction import IQCorrection
from dsp.util import shiftFreq
from misc.general_util import deinterleave
from plots.qt_spectrum_analyzer import AbstractSpectrumAnalyzer


class SpectrumAnalyzerPlot(AbstractSpectrumAnalyzer):
uuid = None

def __init__(self, fs: int, iq: bool = True, buffer: Queue = None, isDead: Value = None, frameRate: int = 0):
super().__init__(fs, iq, frameRate=frameRate)
def __init__(self, fs: int,
iq: bool = False,
buffer: Queue = None,
isDead: Value = None,
frameRate: int = 0,
offset: int = 0):
super().__init__(fs, frameRate=frameRate)
self.buffer = buffer
self.isDead = isDead
self.offset = offset
self.uuid = uuid4()
self.iqCorrector = IQCorrection(self.fs) if iq else None

def __del__(self):
self.buffer.close()
self.buffer.cancel_join_thread()

def receiveData(self):
return deinterleave(self.buffer.get())
data = deinterleave(self.buffer.get())
if self.iqCorrector is not None:
data = self.iqCorrector.correctIq(data)
return shiftFreq(data, self.offset, self.fs)

@classmethod
def processData(cls, isDead, buffer, fs):
cls.start(fs, buffer=buffer, isDead=isDead)
def processData(cls, isDead, buffer, fs, **kwargs):
cls.start(fs, buffer=buffer, isDead=isDead, **kwargs)

def update(self):
from pyqtgraph.Qt.QtCore import QCoreApplication
Expand Down
9 changes: 6 additions & 3 deletions src/sdr/output_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from contextlib import closing
from queue import Queue

from misc.general_util import vprint, shutdownSocket, initializer, eprint
from misc.general_util import shutdownSocket, eprint
from misc.hooked_thread import HookedThread


Expand All @@ -35,14 +35,17 @@ def findPort(host='localhost') -> int:
return s.getsockname()[1]


def log(*args, **kwargs) -> None:
eprint(*args, **kwargs)

def initServer(recvSckt, isDead, host='0.0.0.0', port=findPort()):
clients = []
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass

class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
vprint(f'Connection request from {self.request.getsockname()}')
log(f'Connection request from {self.request.getsockname()}')
buffer = Queue()
clients.append(buffer)
if not recvSckt.barrier.broken:
Expand All @@ -52,7 +55,7 @@ def handle(self):
data = buffer.get()
self.request.sendall(data)
except (ValueError, ConnectionError, EOFError):
eprint(f'Client disconnected: {self.request.getsockname()}')
log(f'Client disconnected: {self.request.getsockname()}')
shutdownSocket(self.request)
clients.remove(buffer)
break
Expand Down
38 changes: 25 additions & 13 deletions src/sdrcontrol.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class SdrControl(App):
offset = reactive(0)
fs = reactive(0)
gain = reactive(0)
freq = reactive(0)

def __init__(self,
rs: socket,
Expand Down Expand Up @@ -87,21 +88,21 @@ def onConnectorPressed(self, event: Button.Pressed) -> None:
fs = fsList.value
fs = fs if str(fs) != "Select.BLANK" else 1024000
freq = frequency.value
freq = int(freq) if freq else 100000000
self.freq = int(freq) if freq else 100000000
agc = self.query_one('#agc_switch', Switch).value
agc = agc if agc else 0
dagc = self.query_one('#dagc_switch', Switch).value
dagc = dagc if dagc else 0

self.controller.setFs(fs)
self.controller.setFrequency(freq + self.offset)
self.controller.setFrequency(self.freq + self.offset)
self.controller.setParam(RtlTcpCommands.SET_GAIN_MODE.value, 1 - agc)
self.controller.setParam(RtlTcpCommands.SET_AGC_MODE.value, dagc)
self.controller.setParam(RtlTcpCommands.SET_TUNER_GAIN_BY_INDEX.value, gain)

gainsSlider.value = gain
fsList.value = fs
frequency.value = str(freq)
frequency.value = freq

result = f'Accepting connections on port {self.server.socket.getsockname()[1]}'
except (ConnectionError, OSError) as e:
Expand All @@ -123,20 +124,28 @@ def onConnectorPressed(self, event: Button.Pressed) -> None:
@on(Select.Changed, '#fs_list')
def onFsChanged(self, event: Select.Changed) -> None:
self.fs = event.value if str(event.value) != "Select.BLANK" else 0
nyquistFs = self.fs >> 1
slider = self.query_one('#offset', Slider)
slider.min = -nyquistFs
slider.max = nyquistFs
slider.value = 0
slider.disabled = False
if self.controller:
self.controller.setFs(self.fs)

@on(Button.Pressed, '#set_freq')
def onFreqPressed(self, _: Button.Pressed) -> None:
if self.controller:
value = self.query_one('#frequency', Input).value
value = int(value) if value else 0
self.controller.setFrequency(value + self.offset)
self.freq = int(value) if value else 0
self.controller.setFrequency(self.freq + self.offset)

@on(Input.Changed, '#offset')
def onOffsetChanged(self, event: Input.Changed) -> None:
value = event.value
self.offset = int(value) if value and value != '-' else 0
@on(Slider.Changed, '#offset')
def onOffsetChanged(self, event: Slider.Changed) -> None:
self.offset = event.value
self.query_one('#offset_label', Label).update(str(self.offset))
if self.controller:
self.controller.setFrequency(self.freq + self.offset)

@on(Slider.Changed, '#gains_slider')
def onGainsChanged(self, event: Slider.Changed) -> None:
Expand Down Expand Up @@ -208,8 +217,10 @@ def compose(self) -> ComposeResult:
yield Input(placeholder='100000000 Hz', id='frequency', classes='frequency', type='integer')
yield Button('Set', id='set_freq', classes='frequency')

yield Label('Offset')
yield Input(placeholder='35000 Hz', id='offset', classes='offset', type='integer')
with Horizontal():
yield Label('Offset ')
yield Label('None', id='offset_label')
yield Slider(-12500, 12500, id='offset', disabled=True, value=0, step=12500)

yield Label('Sampling Rate')
yield Select(RtlTcpSamplingRate.tuples(), prompt='Rate', classes='fs', id='fs_list')
Expand All @@ -224,7 +235,7 @@ def compose(self) -> ComposeResult:
yield Label('Gains')
with Horizontal():
with Vertical():
yield Center(Label('Gain', id='gains_label'))
yield Center(Label('', id='gains_label'))
yield Center(Slider(0, 28, id='gains_slider'))
with Vertical():
yield Center(Label('VGA'))
Expand All @@ -235,7 +246,8 @@ def compose(self) -> ComposeResult:

log = RichLog(highlight=True)
yield log
SdrControl.print = globals()['eprint'] = log.write
SdrControl.print = log.write
setattr(output_server, 'log', log.write)

def on_mount(self) -> None:
label = self.query_one('#gains_label', Label)
Expand Down