add fac,constellation,gl/nongl
git-svn-id: http://op25.osmocom.org/svn/trunk@291 65a5c917-d112-43f1-993d-58c26a4786be
This commit is contained in:
parent
ad335ff1e6
commit
7d86e01d42
|
@ -61,6 +61,7 @@ ourlib_LTLIBRARIES = _repeater.la
|
|||
_repeater_la_SOURCES = repeater\
|
||||
repeater.cc \
|
||||
repeater_fsk4_slicer_fb.cc \
|
||||
repeater_s2v.cc \
|
||||
repeater_p25_frame_assembler.cc \
|
||||
repeater_pipe.cc \
|
||||
repeater_ctcss_squelch_ff.cc \
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix
|
||||
#include "repeater_squelch_base_ff.h"
|
||||
#include "repeater_fsk4_slicer_fb.h"
|
||||
#include "repeater_s2v.h"
|
||||
#include "repeater_p25_frame_assembler.h"
|
||||
#include "repeater_pipe.h"
|
||||
#include "repeater_ctcss_squelch_ff.h"
|
||||
|
@ -155,3 +156,14 @@ private:
|
|||
public:
|
||||
void unkey(void);
|
||||
};
|
||||
|
||||
GR_SWIG_BLOCK_MAGIC(repeater,s2v);
|
||||
|
||||
repeater_s2v_sptr repeater_make_s2v (size_t item_size, size_t nitems_per_block);
|
||||
|
||||
class repeater_s2v : public gr_block
|
||||
{
|
||||
private:
|
||||
repeater_s2v (size_t item_size, size_t nitems_per_block);
|
||||
};
|
||||
|
||||
|
|
|
@ -114,26 +114,20 @@ repeater_p25_frame_assembler::general_work (int noutput_items,
|
|||
|
||||
for (int i = 0; i < noutput_items; i++){
|
||||
if(framer->rx_sym(in[i])) { // complete frame was detected
|
||||
if (d_debug > 0 && framer->duid == 0x00) {
|
||||
if (d_debug >= 10) {
|
||||
fprintf (stderr, "NAC 0x%X DUID 0x%X len %ld errs %d ", framer->nac, framer->duid, framer->frame_size >> 1, framer->bch_errors);
|
||||
}
|
||||
if (d_debug >= 10 && framer->duid == 0x00) {
|
||||
ProcHDU(framer->frame_body);
|
||||
} else if (d_debug > 10 && framer->duid == 0x05) {
|
||||
ProcLDU1(framer->frame_body);
|
||||
} else if (d_debug >= 10 && framer->duid == 0x0a) {
|
||||
ProcLDU2(framer->frame_body);
|
||||
} else if (d_debug > 10 && framer->duid == 0x0f) {
|
||||
ProcTDU(framer->frame_body);
|
||||
}
|
||||
if (d_debug > 10) {
|
||||
fprintf (stderr, "NAC 0x%X DUID 0x%X symbols %d BCH errors %d\n", framer->nac, framer->duid, framer->frame_size >> 1, framer->bch_errors);
|
||||
switch(framer->duid) {
|
||||
case 0x00: // Header DU
|
||||
// see above ProcHDU(framer->frame_body);
|
||||
break;
|
||||
case 0x05: // LDU 1
|
||||
ProcLDU1(framer->frame_body);
|
||||
break;
|
||||
case 0x0a: // LDU 2
|
||||
ProcLDU2(framer->frame_body);
|
||||
break;
|
||||
case 0x0f: // LDU 2
|
||||
ProcTDU(framer->frame_body);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (d_debug >= 10)
|
||||
fprintf(stderr, "\n");
|
||||
if (d_do_imbe && (framer->duid == 0x5 || framer->duid == 0xa)) { // if voice - ldu1 or ldu2
|
||||
for(size_t i = 0; i < nof_voice_codewords; ++i) {
|
||||
voice_codeword cw(voice_codeword_sz);
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2004 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Radio; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2010, KA1RBI
|
||||
*/
|
||||
/*
|
||||
* config.h is generated by configure. It contains the results
|
||||
* of probing for features, options etc. It should be the first
|
||||
* file included in your .cc file.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <repeater_s2v.h>
|
||||
#include <gr_io_signature.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Create a new instance of repeater_s2v and return
|
||||
* a boost shared_ptr. This is effectively the public constructor.
|
||||
*/
|
||||
repeater_s2v_sptr
|
||||
repeater_make_s2v (size_t item_size, size_t nitems_per_block)
|
||||
{
|
||||
return repeater_s2v_sptr (new repeater_s2v (item_size, nitems_per_block));
|
||||
}
|
||||
|
||||
/*
|
||||
* The private constructor
|
||||
*/
|
||||
repeater_s2v::repeater_s2v (size_t item_size, size_t nitems_per_block)
|
||||
: gr_block ("s2v",
|
||||
gr_make_io_signature (1, 1, item_size),
|
||||
gr_make_io_signature (1, 1, item_size * nitems_per_block)),
|
||||
d_buf_len(0),
|
||||
d_acct (0),
|
||||
d_item_size (item_size),
|
||||
d_nitems_per_block (nitems_per_block)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Our virtual destructor.
|
||||
*/
|
||||
repeater_s2v::~repeater_s2v ()
|
||||
{
|
||||
// nothing else required in this example
|
||||
}
|
||||
|
||||
static int min(int a, int b) { return ((a<b) ? a : b); }
|
||||
|
||||
int
|
||||
repeater_s2v::general_work (int noutput_items,
|
||||
gr_vector_int &ninput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
const float *in = (const float *) input_items[0];
|
||||
unsigned char *out = (unsigned char *) output_items[0];
|
||||
size_t rc=0, amt_left=0, amt_move=0;
|
||||
|
||||
amt_left = DBUFSIZE - d_buf_len;
|
||||
amt_move = min(amt_left, ninput_items[0]);
|
||||
if (amt_move > 0) {
|
||||
memcpy (&d_buf[ d_buf_len * d_item_size ], in, amt_move * d_item_size);
|
||||
d_buf_len += amt_move;
|
||||
}
|
||||
|
||||
if (d_buf_len >= d_nitems_per_block) {
|
||||
memcpy (out, d_buf, d_item_size * d_nitems_per_block);
|
||||
d_buf_len = 0;
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
consume_each(amt_move);
|
||||
|
||||
// fprintf(stderr, "d_acct %ld rc %ld amt_left %ld amt_move %ld d_buf_len %ld\n", d_acct, rc, amt_left, amt_move, d_buf_len);
|
||||
|
||||
// Tell runtime system how many output items we produced.
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2004 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Radio; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef INCLUDED_REPEATER_S2V_H
|
||||
#define INCLUDED_REPEATER_S2V_H
|
||||
|
||||
#include <gr_block.h>
|
||||
|
||||
class repeater_s2v;
|
||||
|
||||
/*
|
||||
* We use boost::shared_ptr's instead of raw pointers for all access
|
||||
* to gr_blocks (and many other data structures). The shared_ptr gets
|
||||
* us transparent reference counting, which greatly simplifies storage
|
||||
* management issues. This is especially helpful in our hybrid
|
||||
* C++ / Python system.
|
||||
*
|
||||
* See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
|
||||
*
|
||||
* As a convention, the _sptr suffix indicates a boost::shared_ptr
|
||||
*/
|
||||
typedef boost::shared_ptr<repeater_s2v> repeater_s2v_sptr;
|
||||
|
||||
/*!
|
||||
* \brief Return a shared_ptr to a new instance of repeater_fsk4_slicer_fb.
|
||||
*
|
||||
* To avoid accidental use of raw pointers, repeater_s2v's
|
||||
* constructor is private. repeater_make_s2v is the public
|
||||
* interface for creating new instances.
|
||||
*/
|
||||
repeater_s2v_sptr repeater_make_s2v (size_t item_size, size_t nitems_per_block);
|
||||
|
||||
class repeater_s2v : public gr_block
|
||||
{
|
||||
private:
|
||||
// The friend declaration allows repeater_make_s2v to
|
||||
// access the private constructor.
|
||||
|
||||
friend repeater_s2v_sptr repeater_make_s2v (size_t item_size, size_t nitems_per_block);
|
||||
|
||||
repeater_s2v (size_t item_size, size_t nitems_per_block);
|
||||
|
||||
static const int DBUFSIZE = 65536;
|
||||
|
||||
char d_buf[ DBUFSIZE * sizeof(gr_complex) ];
|
||||
size_t d_buf_len;
|
||||
|
||||
size_t d_acct;
|
||||
size_t d_item_size;
|
||||
size_t d_nitems_per_block;
|
||||
|
||||
public:
|
||||
~repeater_s2v (); // public destructor
|
||||
|
||||
// Where all the action really happens
|
||||
|
||||
int general_work (int noutput_items,
|
||||
gr_vector_int &ninput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items);
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_REPEATER_S2V_H */
|
|
@ -493,7 +493,7 @@ uint32_t ALGID = (HB[40] & 15) * 16 + (HB[41] >> 2);
|
|||
uint32_t KID = (HB[41] & 3) * 16384 + HB[42] * 256 + HB[43] * 4 + (HB[44] >> 4);
|
||||
uint32_t TGID = (HB[44] & 15) * 4096 + HB[45] * 64 + HB[46];
|
||||
|
||||
fprintf (stderr, "HDU: rc %d mfid %x alg %x kid %x tgid %d\n", ec, MFID, ALGID, KID, TGID);
|
||||
fprintf (stderr, " HDU: rc %d mfid %x alg %x kid %x tgid %d", ec, MFID, ALGID, KID, TGID);
|
||||
|
||||
}
|
||||
|
||||
|
@ -518,7 +518,7 @@ void ProcLC(uint8_t HB[]) {
|
|||
int pb = HB[39] >> 5;
|
||||
int sf = (HB[39] & 16) >> 4;
|
||||
int lco = (HB[39] and 15) * 4 + (HB[40] >> 4);
|
||||
fprintf(stderr, "LC: rc %d pb %d sf %d lco %d\n", ec, pb, sf, lco);
|
||||
fprintf(stderr, " LC: rc %d pb %d sf %d lco %d", ec, pb, sf, lco);
|
||||
}
|
||||
|
||||
void ProcLDU1(const_bit_vector A) {
|
||||
|
@ -537,11 +537,11 @@ void ProcLDU2(const_bit_vector A) {
|
|||
uint32_t ALGID = HB[51] * 4 + (HB[52] >> 4);
|
||||
uint32_t KID = (HB[52] & 15) * 4096 + HB[53] * 64 + HB[54];
|
||||
|
||||
fprintf(stderr, "LDU2: rc %d ALGID %x KID %x MI ", ec, ALGID, KID);
|
||||
fprintf(stderr, " LDU2: rc %d ALGID %x KID %x MI ", ec, ALGID, KID);
|
||||
for (int i = 39; i <= 50; i++) {
|
||||
fprintf(stderr, "%02x ", HB[ i ]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
// fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void ProcTDU(const_bit_vector A) {
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Copyright 2008-2011 Steve Glass
|
||||
#
|
||||
# Copyright 2011 KA1RBI
|
||||
#
|
||||
# Copyright 2003,2004,2005,2006 Free Software Foundation, Inc.
|
||||
# (from radiorausch)
|
||||
#
|
||||
# This file is part of OP25 and part of GNU Radio
|
||||
#
|
||||
# OP25 is free software; you can redistribute it and/or modify it
|
||||
|
@ -30,6 +35,7 @@ import math
|
|||
import numpy
|
||||
import time
|
||||
import re
|
||||
import Numeric
|
||||
|
||||
from gnuradio import audio, eng_notation, fsk4, gr, gru, repeater
|
||||
from gnuradio import blks2
|
||||
|
@ -88,6 +94,7 @@ class p25_rx_block (stdgui2.std_top_block):
|
|||
self.usrp = usrp.source_c()
|
||||
self.channel_rate = self.usrp.adc_freq() / options.decim
|
||||
except Exception:
|
||||
print "USRP source_c creation failure"
|
||||
ignore = True
|
||||
|
||||
if options.audio:
|
||||
|
@ -109,6 +116,8 @@ class p25_rx_block (stdgui2.std_top_block):
|
|||
self.datascope_raw_input = False
|
||||
self.data_scope_connected = False
|
||||
|
||||
self.constellation_scope_connected = False
|
||||
|
||||
self.options = options
|
||||
|
||||
for i in xrange(len(speeds)):
|
||||
|
@ -192,9 +201,9 @@ class p25_rx_block (stdgui2.std_top_block):
|
|||
|
||||
self.fft_state = False
|
||||
self.c4fm_state = False
|
||||
self.cscope_state = False
|
||||
self.fscope_state = False
|
||||
self.corr_state = False
|
||||
self.fac_state = False
|
||||
self.fsk4_demod_connected = False
|
||||
self.psk_demod_connected = False
|
||||
self.fsk4_demod_mode = True
|
||||
|
@ -318,12 +327,18 @@ class p25_rx_block (stdgui2.std_top_block):
|
|||
self.connect_fsk4_demod()
|
||||
|
||||
def set_connection(self,
|
||||
cscope=False,
|
||||
fscope=False,
|
||||
fft=False,
|
||||
corr=False,
|
||||
fac=False,
|
||||
c4fm=False):
|
||||
# assumes that lock is held, or that we are in init
|
||||
if fac != self.fac_state:
|
||||
self.fac_state = fac
|
||||
if fac:
|
||||
self.connect(self.mixer, self.fac_scope)
|
||||
else:
|
||||
self.disconnect(self.mixer, self.fac_scope)
|
||||
if corr != self.corr_state:
|
||||
self.corr_state = corr
|
||||
if corr:
|
||||
|
@ -337,15 +352,6 @@ class p25_rx_block (stdgui2.std_top_block):
|
|||
else:
|
||||
self.disconnect(self.symbol_filter, self.correlation_scope)
|
||||
|
||||
if cscope != self.cscope_state:
|
||||
self.cscope_state = cscope
|
||||
if cscope == 0:
|
||||
# self.disconnect(self.diffdec, self.complex_scope)
|
||||
self.disconnect(self.clock, self.complex_scope)
|
||||
else:
|
||||
# self.connect(self.diffdec, self.complex_scope)
|
||||
self.connect(self.clock, self.complex_scope)
|
||||
|
||||
if fscope != self.fscope_state:
|
||||
self.fscope_state = fscope
|
||||
if fscope == 0:
|
||||
|
@ -371,30 +377,36 @@ class p25_rx_block (stdgui2.std_top_block):
|
|||
sel = self.notebook.GetSelection()
|
||||
self.lock()
|
||||
self.disconnect_data_scope()
|
||||
self.disconnect_constellation_scope()
|
||||
if sel == 0: # spectrum
|
||||
if not self.baseband_input:
|
||||
self.set_connection(fft=1)
|
||||
self.disconnect_demods()
|
||||
if sel == 1: # c4fm
|
||||
elif sel == 1: # c4fm
|
||||
self.set_connection(c4fm=1)
|
||||
self.connect_fsk4_demod()
|
||||
if sel == 2: # datascope
|
||||
elif sel == 2: # datascope
|
||||
self.set_connection()
|
||||
self.connect_fsk4_demod()
|
||||
self.connect_data_scope()
|
||||
if sel == 3: # constellation (complex)
|
||||
elif sel == 3: # constellation (complex)
|
||||
if not self.baseband_input:
|
||||
self.set_connection(cscope=1)
|
||||
self.set_connection()
|
||||
self.connect_psk_demod()
|
||||
if sel == 4: # demodulated symbols
|
||||
self.connect_constellation_scope()
|
||||
elif sel == 4: # demodulated symbols
|
||||
self.connect_demods()
|
||||
self.set_connection(fscope=1)
|
||||
if sel == 5: # correlation
|
||||
elif sel == 5: # correlation
|
||||
self.disconnect_demods()
|
||||
self.current_speed = self.default_speed_idx # reset speed for corr
|
||||
self.data_scope.win.radio_box_speed.SetSelection(self.current_speed)
|
||||
self.connect_fsk4_demod()
|
||||
self.set_connection(corr=1)
|
||||
elif sel == 6: # fac - fast auto correlation
|
||||
if not self.baseband_input:
|
||||
self.set_connection(fac=1)
|
||||
self.disconnect_demods()
|
||||
self.unlock()
|
||||
|
||||
# initialize the UI
|
||||
|
@ -467,13 +479,19 @@ class p25_rx_block (stdgui2.std_top_block):
|
|||
self.vbox.Add(self.notebook, 1, wx.EXPAND)
|
||||
# add spectrum scope
|
||||
self.spectrum = fftsink2.fft_sink_c(self.notebook, sample_rate = self.channel_rate, fft_size=512, fft_rate=2, average=False, peak_hold=False)
|
||||
self.spectrum_plotter = self.spectrum.win.plotter
|
||||
self.spectrum_plotter.enable_point_label(False)
|
||||
try:
|
||||
self.spectrum_plotter = self.spectrum.win.plotter
|
||||
except:
|
||||
self.spectrum_plotter = self.spectrum.win.plot
|
||||
#self.spectrum_plotter.enable_point_label(False)
|
||||
self.spectrum_plotter.Bind(wx.EVT_LEFT_DOWN, self._on_spectrum_left_click)
|
||||
self.notebook.AddPage(self.spectrum.win, "RF Spectrum")
|
||||
# add C4FM scope
|
||||
self.signal_scope = scopesink2.scope_sink_f(self.notebook, sample_rate = self.basic_rate, v_scale=5, t_scale=0.001)
|
||||
self.signal_plotter = self.signal_scope.win.plotter
|
||||
try:
|
||||
self.signal_plotter = self.signal_scope.win.plotter
|
||||
except:
|
||||
self.signal_plotter = self.signal_scope.win.graph
|
||||
self.notebook.AddPage(self.signal_scope.win, "C4FM Signal")
|
||||
# add datascope
|
||||
self.data_scope = datascope_sink_f(self.notebook, samples_per_symbol = 10, num_plots = 100)
|
||||
|
@ -485,19 +503,27 @@ class p25_rx_block (stdgui2.std_top_block):
|
|||
# add complex scope
|
||||
self.complex_scope = constellation_plot_c(self.notebook, title="Constellation", num_plots=250)
|
||||
self.notebook.AddPage(self.complex_scope.win, "Constellation")
|
||||
wx.EVT_RADIOBOX(self.complex_scope.win.radio_box_source, 11108, self.source_select)
|
||||
# add float scope
|
||||
self.float_scope = scopesink2.scope_sink_f(self.notebook, frame_decim=1, sample_rate=self.symbol_rate, v_scale=1, t_scale=0.05)
|
||||
self.float_plotter = self.float_scope.win.plotter
|
||||
self.float_scope.win['marker_1'] = 3.0 # set type = large dots
|
||||
try: #gl
|
||||
self.float_plotter = self.float_scope.win.plotter
|
||||
self.float_scope.win['marker_1'] = 3.0 # set type = large dots
|
||||
except: #nongl
|
||||
self.float_plotter = self.float_scope.win.graph
|
||||
self.float_scope.win.set_format_plus()
|
||||
self.notebook.AddPage(self.float_scope.win, "Demodulated Symbols")
|
||||
# Traffic snapshot
|
||||
# self.traffic = TrafficPane(self.notebook)
|
||||
# self.notebook.AddPage(self.traffic, "Traffic")
|
||||
# add float scope
|
||||
# add corr scope
|
||||
self.correlation_scope = correlation_plot_f(self.notebook, frame_decim=4, sps=10, v_scale=1, t_scale=0.05)
|
||||
# self.correlation_plotter = self.correlation_scope.win.plotter
|
||||
wx.EVT_RADIOBOX(self.correlation_scope.win.radio_box_corr, 11105, self.corr_select)
|
||||
self.notebook.AddPage(self.correlation_scope.win, "Correlation")
|
||||
# add fac scope
|
||||
self.fac_scope = fac_sink_c(self.notebook, fac_size=32768, sample_rate=self.channel_rate, title="Auto Correlation")
|
||||
self.notebook.AddPage(self.fac_scope.win, "Auto Correlation")
|
||||
# Setup the decoder and report the TUN/TAP device name
|
||||
msgq = gr.msg_queue(2)
|
||||
# self.decode_watcher = decode_watcher(msgq, self.traffic)
|
||||
|
@ -943,6 +969,22 @@ class p25_rx_block (stdgui2.std_top_block):
|
|||
else:
|
||||
self.connect_psk_demod()
|
||||
|
||||
def disconnect_constellation_scope(self):
|
||||
if self.constellation_scope_connected:
|
||||
self.disconnect(self.constellation_scope_input, self.complex_scope)
|
||||
self.constellation_scope_connected = False
|
||||
self.constellation_scope_input = None
|
||||
|
||||
def connect_constellation_scope(self):
|
||||
self.disconnect_constellation_scope()
|
||||
sel = self.complex_scope.win.radio_box_source.GetSelection()
|
||||
if sel:
|
||||
self.constellation_scope_input = self.diffdec
|
||||
else:
|
||||
self.constellation_scope_input = self.clock
|
||||
self.constellation_scope_connected = True
|
||||
self.connect(self.constellation_scope_input, self.complex_scope)
|
||||
|
||||
def disconnect_data_scope(self):
|
||||
if self.data_scope_connected:
|
||||
self.disconnect(self.data_scope_input, self.data_scope)
|
||||
|
@ -980,6 +1022,11 @@ class p25_rx_block (stdgui2.std_top_block):
|
|||
self.set_connection(corr=True)
|
||||
self.unlock()
|
||||
|
||||
def source_select(self, evt):
|
||||
self.lock()
|
||||
self.connect_constellation_scope()
|
||||
self.unlock()
|
||||
|
||||
def speed_select(self, evt):
|
||||
new_speed = self.data_scope.win.radio_box_speed.GetSelection()
|
||||
self.lock()
|
||||
|
@ -1553,21 +1600,22 @@ class constellation_plot_input_watcher (threading.Thread):
|
|||
|
||||
class constellation_plot_window (wx.Panel):
|
||||
|
||||
constellation_window_size = wx.DefaultSize
|
||||
def __init__ (self, info, parent, id = -1,
|
||||
num_plots=100,
|
||||
pos = wx.DefaultPosition, size = wx.DefaultSize, name = ""):
|
||||
pos = wx.DefaultPosition, size = constellation_window_size, name = ""):
|
||||
wx.Panel.__init__ (self, parent, -1)
|
||||
self.info = info
|
||||
|
||||
vbox = wx.BoxSizer (wx.VERTICAL)
|
||||
hbox = wx.BoxSizer (wx.HORIZONTAL)
|
||||
|
||||
self.graph = constellation_plot_graph_window (info, self, -1, num_plots=num_plots)
|
||||
|
||||
vbox.Add (self.graph, 1, wx.EXPAND)
|
||||
vbox.Add (self.make_control_box(), 0, wx.EXPAND)
|
||||
vbox.Add (self.make_control2_box(), 0, wx.EXPAND)
|
||||
hbox.Add (self.graph, 1, wx.SHAPED)
|
||||
hbox.Add (self.make_control_box(), 0, wx.EXPAND)
|
||||
hbox.Add (self.make_control2_box(), 0, wx.EXPAND)
|
||||
|
||||
self.sizer = vbox
|
||||
self.sizer = hbox
|
||||
self.SetSizer (self.sizer)
|
||||
self.SetAutoLayout (True)
|
||||
self.sizer.Fit (self)
|
||||
|
@ -1591,10 +1639,20 @@ class constellation_plot_window (wx.Panel):
|
|||
wx.EVT_BUTTON (self, 11102, self.run_stop)
|
||||
ctrlbox.Add (run_stop, 0, wx.EXPAND)
|
||||
|
||||
self.radio_box = wx.RadioBox(self, 11103, "Viewpoint", style=wx.RA_SPECIFY_ROWS,
|
||||
choices = ["Raw", "Filtered"] )
|
||||
self.radio_box.SetToolTipString("Viewpoint Before Or After Symbol Filter")
|
||||
ctrlbox.Add (self.radio_box, 0, wx.EXPAND)
|
||||
# self.radio_box.SetToolTipString("Viewpoint Before Or After Symbol Filter")
|
||||
|
||||
self.radio_box_mode = wx.RadioBox(self, 11106, "Mode", style=wx.RA_SPECIFY_ROWS,
|
||||
choices = ["Standard", "Population"] )
|
||||
ctrlbox.Add (self.radio_box_mode, 0, wx.EXPAND)
|
||||
|
||||
self.radio_box_color = wx.RadioBox(self, 11107, "Color", style=wx.RA_SPECIFY_ROWS,
|
||||
choices = ["Mono", "2 Color"] )
|
||||
ctrlbox.Add (self.radio_box_color, 0, wx.EXPAND)
|
||||
wx.EVT_RADIOBOX(self.radio_box_color, 11107, self.color_select)
|
||||
|
||||
self.radio_box_source = wx.RadioBox(self, 11108, "Source", style=wx.RA_SPECIFY_ROWS,
|
||||
choices = ["Direct", "Differential"] )
|
||||
ctrlbox.Add (self.radio_box_source, 0, wx.EXPAND)
|
||||
|
||||
ctrlbox.Add ((10, 0) ,1) # stretchy space
|
||||
|
||||
|
@ -1603,6 +1661,15 @@ class constellation_plot_window (wx.Panel):
|
|||
def run_stop (self, evt):
|
||||
self.info.running = not self.info.running
|
||||
|
||||
def color_select(self, evt):
|
||||
sel = self.radio_box_color.GetSelection()
|
||||
if sel:
|
||||
self.graph.color1 = 'red'
|
||||
self.graph.color2 = 'green'
|
||||
else:
|
||||
self.graph.color1 = 'blue'
|
||||
self.graph.color2 = 'blue'
|
||||
|
||||
class constellation_plot_graph_window (plot.PlotCanvas):
|
||||
|
||||
def __init__ (self, info, parent, id = -1,
|
||||
|
@ -1618,6 +1685,7 @@ class constellation_plot_graph_window (plot.PlotCanvas):
|
|||
# self.SetBackgroundColour ('black')
|
||||
|
||||
self.info = info;
|
||||
self.plot_window = parent
|
||||
|
||||
self.total_points = 0
|
||||
|
||||
|
@ -1629,10 +1697,18 @@ class constellation_plot_graph_window (plot.PlotCanvas):
|
|||
|
||||
self.flag = False
|
||||
|
||||
def format_data_orig (self, evt):
|
||||
self.color1 = 'blue'
|
||||
self.color2 = 'blue'
|
||||
|
||||
def format_data (self, evt):
|
||||
if not self.info.running:
|
||||
return
|
||||
if self.plot_window.radio_box_mode.GetSelection():
|
||||
self.format_data_pop(evt)
|
||||
else:
|
||||
self.format_data_std(evt)
|
||||
|
||||
def format_data_std (self, evt):
|
||||
info = self.info
|
||||
records = evt.data
|
||||
nchannels = len (records)
|
||||
|
@ -1655,18 +1731,18 @@ class constellation_plot_graph_window (plot.PlotCanvas):
|
|||
p0.append(p)
|
||||
self.flag = not self.flag
|
||||
|
||||
objects.append (plot.PolyMarker (p0, marker='plus', colour='blue'))
|
||||
objects.append (plot.PolyMarker (p1, marker='plus', colour='blue'))
|
||||
objects.append (plot.PolyMarker (p0, marker='plus', colour=self.color1))
|
||||
objects.append (plot.PolyMarker (p1, marker='plus', colour=self.color2))
|
||||
|
||||
graphics = plot.PlotGraphics (objects,
|
||||
title='Data Scope',
|
||||
title='Constellation',
|
||||
xLabel = 'I', yLabel = 'Q')
|
||||
|
||||
x_range = (-1.0, 1.0)
|
||||
y_range = (-1.0, 1.0)
|
||||
self.Draw (graphics, xAxis=x_range, yAxis=y_range)
|
||||
|
||||
def format_data (self, evt):
|
||||
def format_data_pop (self, evt):
|
||||
if not self.info.running:
|
||||
return
|
||||
|
||||
|
@ -1679,7 +1755,6 @@ class constellation_plot_graph_window (plot.PlotCanvas):
|
|||
self.SetXUseScopeTicks (True) # use 10 divisions, no labels
|
||||
|
||||
objects = []
|
||||
colors = ['red','orange','yellow','green','blue','violet','cyan','magenta','brown','black']
|
||||
|
||||
r = records[0] # input data
|
||||
l = len(r) / 2
|
||||
|
@ -1732,13 +1807,11 @@ class constellation_plot_graph_window (plot.PlotCanvas):
|
|||
sp = p
|
||||
p1.append(p)
|
||||
p1.append(sp)
|
||||
# objects.append (plot.PolyMarker (p0, marker='point', colour='red'))
|
||||
# objects.append (plot.PolyMarker (p1, marker='point', colour='green'))
|
||||
objects.append (plot.PolyLine (p0, colour='red', legend=''))
|
||||
objects.append (plot.PolyLine (p1, colour='green', legend=''))
|
||||
objects.append (plot.PolyLine (p0, colour=self.color1, legend=''))
|
||||
objects.append (plot.PolyLine (p1, colour=self.color2, legend=''))
|
||||
|
||||
graphics = plot.PlotGraphics (objects,
|
||||
title='Data Scope',
|
||||
title='Constellation',
|
||||
xLabel = 'I', yLabel = 'Q')
|
||||
|
||||
x_range = (-2.5, 2.5)
|
||||
|
@ -2003,6 +2076,459 @@ class correlation_plot_graph_window (plot.PlotCanvas):
|
|||
y_range = (-800.0, 800.0)
|
||||
self.Draw (graphics, xAxis=x_range, yAxis=y_range)
|
||||
|
||||
#
|
||||
# following code copied from radiorausch file facsink.py
|
||||
# source: http://sites.google.com/site/radiorausch/
|
||||
#
|
||||
# modified Jul. 2011 to current GR KA1RBI (to fix error messages)
|
||||
#
|
||||
# Copyright 2003,2004,2005,2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GNU Radio
|
||||
#
|
||||
# GNU Radio is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# GNU Radio is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GNU Radio; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
# default_facsink_size = (640,240)
|
||||
default_facsink_size = wx.DefaultSize
|
||||
default_fac_rate = gr.prefs().get_long('wxgui', 'fac_rate', 3) # was 15
|
||||
|
||||
class fac_sink_base(object):
|
||||
def __init__(self, input_is_real=False, baseband_freq=0, y_per_div=10, ref_level=50,
|
||||
sample_rate=1, fac_size=512,
|
||||
fac_rate=default_fac_rate,
|
||||
average=False, avg_alpha=None, title='', peak_hold=False):
|
||||
|
||||
# initialize common attributes
|
||||
self.baseband_freq = baseband_freq
|
||||
self.y_divs = 8
|
||||
self.y_per_div=y_per_div
|
||||
self.ref_level = ref_level
|
||||
self.sample_rate = sample_rate
|
||||
self.fac_size = fac_size
|
||||
self.fac_rate = fac_rate
|
||||
self.average = average
|
||||
if avg_alpha is None:
|
||||
self.avg_alpha = 0.20 / fac_rate # averaging needed to be slowed down for very slow rates
|
||||
else:
|
||||
self.avg_alpha = avg_alpha
|
||||
self.title = title
|
||||
self.peak_hold = peak_hold
|
||||
self.input_is_real = input_is_real
|
||||
self.msgq = gr.msg_queue(2) # queue that holds a maximum of 2 messages
|
||||
|
||||
def set_y_per_div(self, y_per_div):
|
||||
self.y_per_div = y_per_div
|
||||
|
||||
def set_ref_level(self, ref_level):
|
||||
self.ref_level = ref_level
|
||||
|
||||
def set_average(self, average):
|
||||
self.average = average
|
||||
if average:
|
||||
self.avg.set_taps(self.avg_alpha)
|
||||
self.set_peak_hold(False)
|
||||
else:
|
||||
self.avg.set_taps(1.0)
|
||||
|
||||
def set_peak_hold(self, enable):
|
||||
self.peak_hold = enable
|
||||
if enable:
|
||||
self.set_average(False)
|
||||
self.win.set_peak_hold(enable)
|
||||
|
||||
def set_avg_alpha(self, avg_alpha):
|
||||
self.avg_alpha = avg_alpha
|
||||
|
||||
def set_baseband_freq(self, baseband_freq):
|
||||
self.baseband_freq = baseband_freq
|
||||
|
||||
def set_sample_rate(self, sample_rate):
|
||||
self.sample_rate = sample_rate
|
||||
self._set_n()
|
||||
|
||||
def _set_n(self):
|
||||
self.one_in_n.set_n(max(1, int(self.sample_rate/self.fac_size/self.fac_rate)))
|
||||
|
||||
|
||||
class fac_sink_f(gr.hier_block2, fac_sink_base):
|
||||
def __init__(self, parent, baseband_freq=0,
|
||||
y_per_div=10, ref_level=50, sample_rate=1, fac_size=512,
|
||||
fac_rate=default_fac_rate,
|
||||
average=False, avg_alpha=None,
|
||||
title='', size=default_facsink_size, peak_hold=False):
|
||||
|
||||
fac_sink_base.__init__(self, input_is_real=True, baseband_freq=baseband_freq,
|
||||
y_per_div=y_per_div, ref_level=ref_level,
|
||||
sample_rate=sample_rate, fac_size=fac_size,
|
||||
fac_rate=fac_rate,
|
||||
average=average, avg_alpha=avg_alpha, title=title,
|
||||
peak_hold=peak_hold)
|
||||
|
||||
s2p = gr.stream_to_vector(gr.sizeof_float, self.fac_size)
|
||||
self.one_in_n = gr.keep_one_in_n(gr.sizeof_float * self.fac_size,
|
||||
max(1, int(self.sample_rate/self.fac_size/self.fac_rate)))
|
||||
|
||||
|
||||
# windowing removed...
|
||||
|
||||
fac = gr.fft_vfc(self.fac_size, True, ())
|
||||
|
||||
c2mag = gr.complex_to_mag(self.fac_size)
|
||||
self.avg = gr.single_pole_iir_filter_ff(1.0, self.fac_size)
|
||||
|
||||
#
|
||||
fac_fac = gr.fft_vfc(self.fac_size, True, ())
|
||||
fac_c2mag = gr.complex_to_mag(fac_size)
|
||||
|
||||
|
||||
# FIXME We need to add 3dB to all bins but the DC bin
|
||||
log = gr.nlog10_ff(20, self.fac_size,
|
||||
-20*math.log10(self.fac_size) )
|
||||
sink = gr.message_sink(gr.sizeof_float * self.fac_size, self.msgq, True)
|
||||
|
||||
self.connect(self, s2p, self.one_in_n, fac, c2mag, fac_fac, fac_c2mag, self.avg, log, sink)
|
||||
# gr.hier_block.__init__(self, fg, s2p, sink)
|
||||
gr.hier_block2.__init__(self, "fac_sink_f",
|
||||
gr.io_signature(1, 1, gr.sizeof_float),
|
||||
gr.io_signature(0, 0, 0))
|
||||
|
||||
self.win = fac_window(self, parent, size=size)
|
||||
self.set_average(self.average)
|
||||
|
||||
|
||||
|
||||
class fac_sink_c(gr.hier_block2, fac_sink_base):
|
||||
def __init__(self, parent, baseband_freq=0,
|
||||
y_per_div=10, ref_level=90, sample_rate=1, fac_size=512,
|
||||
fac_rate=default_fac_rate,
|
||||
average=False, avg_alpha=None,
|
||||
title='', size=default_facsink_size, peak_hold=False):
|
||||
|
||||
fac_sink_base.__init__(self, input_is_real=False, baseband_freq=baseband_freq,
|
||||
y_per_div=y_per_div, ref_level=ref_level,
|
||||
sample_rate=sample_rate, fac_size=fac_size,
|
||||
fac_rate=fac_rate,
|
||||
average=average, avg_alpha=avg_alpha, title=title,
|
||||
peak_hold=peak_hold)
|
||||
gr.hier_block2.__init__(self, "fac_sink_c",
|
||||
gr.io_signature(1, 1, gr.sizeof_gr_complex),
|
||||
gr.io_signature(0, 0, 0))
|
||||
|
||||
#s2p = gr.stream_to_vector(gr.sizeof_gr_complex, self.fac_size)
|
||||
s2p = repeater.s2v(gr.sizeof_gr_complex, self.fac_size)
|
||||
self.one_in_n = gr.keep_one_in_n(gr.sizeof_gr_complex * self.fac_size,
|
||||
max(1, int(self.sample_rate/self.fac_size/self.fac_rate)))
|
||||
|
||||
|
||||
# windowing removed ...
|
||||
|
||||
fac = gr.fft_vcc(self.fac_size, True, ())
|
||||
c2mag = gr.complex_to_mag(fac_size)
|
||||
|
||||
# Things go off into the weeds if we try for an inverse FFT so a forward FFT will have to do...
|
||||
fac_fac = gr.fft_vfc(self.fac_size, True, ())
|
||||
fac_c2mag = gr.complex_to_mag(fac_size)
|
||||
|
||||
|
||||
self.avg = gr.single_pole_iir_filter_ff(1.0, fac_size)
|
||||
|
||||
log = gr.nlog10_ff(20, self.fac_size,
|
||||
-20*math.log10(self.fac_size) ) # - 20*math.log10(norm) ) # - self.avg[0] )
|
||||
sink = gr.message_sink(gr.sizeof_float * fac_size, self.msgq, True)
|
||||
|
||||
self.connect(self, s2p, self.one_in_n, fac, c2mag, fac_fac, fac_c2mag, self.avg)
|
||||
self.connect(self.avg, log, sink)
|
||||
|
||||
# gr.hier_block.__init__(self, fg, s2p, sink)
|
||||
|
||||
self.win = fac_window(self, parent, size=size)
|
||||
self.set_average(self.average)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
fac_myDATA_EVENT = wx.NewEventType()
|
||||
fac_EVT_DATA_EVENT = wx.PyEventBinder (fac_myDATA_EVENT, 0)
|
||||
|
||||
|
||||
class fac_DataEvent(wx.PyEvent):
|
||||
def __init__(self, data):
|
||||
wx.PyEvent.__init__(self)
|
||||
self.SetEventType (fac_myDATA_EVENT)
|
||||
self.data = data
|
||||
|
||||
def Clone (self):
|
||||
self.__class__ (self.GetId())
|
||||
|
||||
|
||||
class fac_input_watcher (threading.Thread):
|
||||
def __init__ (self, msgq, fac_size, event_receiver, **kwds):
|
||||
threading.Thread.__init__ (self, **kwds)
|
||||
self.setDaemon (1)
|
||||
self.msgq = msgq
|
||||
self.fac_size = fac_size
|
||||
self.event_receiver = event_receiver
|
||||
self.keep_running = True
|
||||
self.start ()
|
||||
|
||||
def run (self):
|
||||
while (self.keep_running):
|
||||
msg = self.msgq.delete_head() # blocking read of message queue
|
||||
itemsize = int(msg.arg1())
|
||||
nitems = int(msg.arg2())
|
||||
|
||||
s = msg.to_string() # get the body of the msg as a string
|
||||
|
||||
# There may be more than one fac frame in the message.
|
||||
# If so, we take only the last one
|
||||
if nitems > 1:
|
||||
start = itemsize * (nitems - 1)
|
||||
s = s[start:start+itemsize]
|
||||
|
||||
complex_data = Numeric.fromstring (s, Numeric.Float32)
|
||||
de = fac_DataEvent (complex_data)
|
||||
wx.PostEvent (self.event_receiver, de)
|
||||
del de
|
||||
|
||||
|
||||
class fac_window (plot.PlotCanvas):
|
||||
def __init__ (self, facsink, parent, id = -1,
|
||||
pos = wx.DefaultPosition, size = wx.DefaultSize,
|
||||
style = wx.DEFAULT_FRAME_STYLE, name = ""):
|
||||
plot.PlotCanvas.__init__ (self, parent, id, pos, size, style, name)
|
||||
|
||||
self.y_range = None
|
||||
self.facsink = facsink
|
||||
self.peak_hold = False
|
||||
self.peak_vals = None
|
||||
|
||||
self.SetEnableGrid (True)
|
||||
# self.SetEnableZoom (True)
|
||||
# self.SetBackgroundColour ('black')
|
||||
|
||||
self.build_popup_menu()
|
||||
|
||||
fac_EVT_DATA_EVENT (self, self.set_data)
|
||||
wx.EVT_CLOSE (self, self.on_close_window)
|
||||
self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
|
||||
|
||||
self.input_watcher = fac_input_watcher(facsink.msgq, facsink.fac_size, self)
|
||||
|
||||
|
||||
def on_close_window (self, event):
|
||||
print "fac_window:on_close_window"
|
||||
self.keep_running = False
|
||||
|
||||
|
||||
def set_data (self, evt):
|
||||
dB = evt.data
|
||||
L = len (dB)
|
||||
|
||||
if self.peak_hold:
|
||||
if self.peak_vals is None:
|
||||
self.peak_vals = dB
|
||||
else:
|
||||
self.peak_vals = Numeric.maximum(dB, self.peak_vals)
|
||||
dB = self.peak_vals
|
||||
|
||||
x = max(abs(self.facsink.sample_rate), abs(self.facsink.baseband_freq))
|
||||
sf = 1000.0
|
||||
units = "ms"
|
||||
|
||||
x_vals = ((Numeric.arrayrange (L/2)
|
||||
* ( (sf / self.facsink.sample_rate ) )) )
|
||||
points = Numeric.zeros((len(x_vals), 2), Numeric.Float64)
|
||||
points[:,0] = x_vals
|
||||
points[:,1] = dB[0:L/2]
|
||||
|
||||
|
||||
lines = plot.PolyLine (points, colour='DARKRED')
|
||||
|
||||
|
||||
graphics = plot.PlotGraphics ([lines],
|
||||
title=self.facsink.title,
|
||||
xLabel = units, yLabel = "dB")
|
||||
|
||||
self.Draw (graphics, xAxis=None, yAxis=self.y_range)
|
||||
self.update_y_range ()
|
||||
|
||||
def set_peak_hold(self, enable):
|
||||
self.peak_hold = enable
|
||||
self.peak_vals = None
|
||||
|
||||
def update_y_range (self):
|
||||
ymax = self.facsink.ref_level
|
||||
ymin = self.facsink.ref_level - self.facsink.y_per_div * self.facsink.y_divs
|
||||
self.y_range = self._axisInterval ('min', ymin, ymax)
|
||||
|
||||
def on_average(self, evt):
|
||||
# print "on_average"
|
||||
self.facsink.set_average(evt.IsChecked())
|
||||
|
||||
def on_peak_hold(self, evt):
|
||||
# print "on_peak_hold"
|
||||
self.facsink.set_peak_hold(evt.IsChecked())
|
||||
|
||||
def on_incr_ref_level(self, evt):
|
||||
# print "on_incr_ref_level"
|
||||
self.facsink.set_ref_level(self.facsink.ref_level
|
||||
+ self.facsink.y_per_div)
|
||||
|
||||
def on_decr_ref_level(self, evt):
|
||||
# print "on_decr_ref_level"
|
||||
self.facsink.set_ref_level(self.facsink.ref_level
|
||||
- self.facsink.y_per_div)
|
||||
|
||||
def on_incr_y_per_div(self, evt):
|
||||
# print "on_incr_y_per_div"
|
||||
self.facsink.set_y_per_div(next_up(self.facsink.y_per_div, (1,2,5,10,20)))
|
||||
|
||||
def on_decr_y_per_div(self, evt):
|
||||
# print "on_decr_y_per_div"
|
||||
self.facsink.set_y_per_div(next_down(self.facsink.y_per_div, (1,2,5,10,20)))
|
||||
|
||||
def on_y_per_div(self, evt):
|
||||
# print "on_y_per_div"
|
||||
Id = evt.GetId()
|
||||
if Id == self.id_y_per_div_1:
|
||||
self.facsink.set_y_per_div(1)
|
||||
elif Id == self.id_y_per_div_2:
|
||||
self.facsink.set_y_per_div(2)
|
||||
elif Id == self.id_y_per_div_5:
|
||||
self.facsink.set_y_per_div(5)
|
||||
elif Id == self.id_y_per_div_10:
|
||||
self.facsink.set_y_per_div(10)
|
||||
elif Id == self.id_y_per_div_20:
|
||||
self.facsink.set_y_per_div(20)
|
||||
|
||||
|
||||
def on_right_click(self, event):
|
||||
menu = self.popup_menu
|
||||
for id, pred in self.checkmarks.items():
|
||||
item = menu.FindItemById(id)
|
||||
item.Check(pred())
|
||||
self.PopupMenu(menu, event.GetPosition())
|
||||
|
||||
|
||||
def build_popup_menu(self):
|
||||
self.id_incr_ref_level = wx.NewId()
|
||||
self.id_decr_ref_level = wx.NewId()
|
||||
self.id_incr_y_per_div = wx.NewId()
|
||||
self.id_decr_y_per_div = wx.NewId()
|
||||
self.id_y_per_div_1 = wx.NewId()
|
||||
self.id_y_per_div_2 = wx.NewId()
|
||||
self.id_y_per_div_5 = wx.NewId()
|
||||
self.id_y_per_div_10 = wx.NewId()
|
||||
self.id_y_per_div_20 = wx.NewId()
|
||||
self.id_average = wx.NewId()
|
||||
self.id_peak_hold = wx.NewId()
|
||||
|
||||
self.Bind(wx.EVT_MENU, self.on_average, id=self.id_average)
|
||||
self.Bind(wx.EVT_MENU, self.on_peak_hold, id=self.id_peak_hold)
|
||||
self.Bind(wx.EVT_MENU, self.on_incr_ref_level, id=self.id_incr_ref_level)
|
||||
self.Bind(wx.EVT_MENU, self.on_decr_ref_level, id=self.id_decr_ref_level)
|
||||
self.Bind(wx.EVT_MENU, self.on_incr_y_per_div, id=self.id_incr_y_per_div)
|
||||
self.Bind(wx.EVT_MENU, self.on_decr_y_per_div, id=self.id_decr_y_per_div)
|
||||
self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_1)
|
||||
self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_2)
|
||||
self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_5)
|
||||
self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_10)
|
||||
self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_20)
|
||||
|
||||
|
||||
# make a menu
|
||||
menu = wx.Menu()
|
||||
self.popup_menu = menu
|
||||
menu.AppendCheckItem(self.id_average, "Average")
|
||||
menu.AppendCheckItem(self.id_peak_hold, "Peak Hold")
|
||||
menu.Append(self.id_incr_ref_level, "Incr Ref Level")
|
||||
menu.Append(self.id_decr_ref_level, "Decr Ref Level")
|
||||
# menu.Append(self.id_incr_y_per_div, "Incr dB/div")
|
||||
# menu.Append(self.id_decr_y_per_div, "Decr dB/div")
|
||||
menu.AppendSeparator()
|
||||
# we'd use RadioItems for these, but they're not supported on Mac
|
||||
menu.AppendCheckItem(self.id_y_per_div_1, "1 dB/div")
|
||||
menu.AppendCheckItem(self.id_y_per_div_2, "2 dB/div")
|
||||
menu.AppendCheckItem(self.id_y_per_div_5, "5 dB/div")
|
||||
menu.AppendCheckItem(self.id_y_per_div_10, "10 dB/div")
|
||||
menu.AppendCheckItem(self.id_y_per_div_20, "20 dB/div")
|
||||
|
||||
self.checkmarks = {
|
||||
self.id_average : lambda : self.facsink.average,
|
||||
self.id_peak_hold : lambda : self.facsink.peak_hold,
|
||||
self.id_y_per_div_1 : lambda : self.facsink.y_per_div == 1,
|
||||
self.id_y_per_div_2 : lambda : self.facsink.y_per_div == 2,
|
||||
self.id_y_per_div_5 : lambda : self.facsink.y_per_div == 5,
|
||||
self.id_y_per_div_10 : lambda : self.facsink.y_per_div == 10,
|
||||
self.id_y_per_div_20 : lambda : self.facsink.y_per_div == 20,
|
||||
}
|
||||
|
||||
|
||||
def next_up(v, seq):
|
||||
"""
|
||||
Return the first item in seq that is > v.
|
||||
"""
|
||||
for s in seq:
|
||||
if s > v:
|
||||
return s
|
||||
return v
|
||||
|
||||
def next_down(v, seq):
|
||||
"""
|
||||
Return the last item in seq that is < v.
|
||||
"""
|
||||
rseq = list(seq[:])
|
||||
rseq.reverse()
|
||||
|
||||
for s in rseq:
|
||||
if s < v:
|
||||
return s
|
||||
return v
|
||||
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Deprecated interfaces
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# returns (block, win).
|
||||
# block requires a single input stream of float
|
||||
# win is a subclass of wxWindow
|
||||
|
||||
def make_fac_sink_f(fg, parent, title, fac_size, input_rate, ymin = 0, ymax=50):
|
||||
|
||||
block = fac_sink_f(fg, parent, title=title, fac_size=fac_size, sample_rate=input_rate,
|
||||
y_per_div=(ymax - ymin)/8, ref_level=ymax)
|
||||
return (block, block.win)
|
||||
|
||||
# returns (block, win).
|
||||
# block requires a single input stream of gr_complex
|
||||
# win is a subclass of wxWindow
|
||||
|
||||
def make_fac_sink_c(fg, parent, title, fac_size, input_rate, ymin=0, ymax=50):
|
||||
block = fac_sink_c(fg, parent, title=title, fac_size=fac_size, sample_rate=input_rate,
|
||||
y_per_div=(ymax - ymin)/8, ref_level=ymax)
|
||||
return (block, block.win)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Standalone test app - deleted
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
|
||||
############################################################################
|
||||
|
||||
# Start the receiver
|
||||
|
|
Reference in New Issue