diff options
Diffstat (limited to 'gr-qtgui/lib/freq_sink_c_impl.cc')
-rw-r--r-- | gr-qtgui/lib/freq_sink_c_impl.cc | 225 |
1 files changed, 169 insertions, 56 deletions
diff --git a/gr-qtgui/lib/freq_sink_c_impl.cc b/gr-qtgui/lib/freq_sink_c_impl.cc index 11e8fc378f..e46b9db865 100644 --- a/gr-qtgui/lib/freq_sink_c_impl.cc +++ b/gr-qtgui/lib/freq_sink_c_impl.cc @@ -54,8 +54,8 @@ namespace gr { int nconnections, QWidget *parent) : sync_block("freq_sink_c", - io_signature::make(1, -1, sizeof(gr_complex)), - io_signature::make(0, 0, 0)), + io_signature::make(nconnections, nconnections, sizeof(gr_complex)), + io_signature::make(0, 0, 0)), d_fftsize(fftsize), d_fftavg(1.0), d_wintype((filter::firdes::win_type)(wintype)), d_center_freq(fc), d_bandwidth(bw), d_name(name), @@ -87,6 +87,11 @@ namespace gr { volk_get_alignment()); memset(d_fbuf, 0, d_fftsize*sizeof(float)); + d_tmpbuflen = (unsigned int)(floor(d_fftsize/2.0)); + d_tmpbuf = (float*)volk_malloc(sizeof(float)*(d_tmpbuflen + 1), + volk_get_alignment()); + + d_index = 0; for(int i = 0; i < d_nconnections; i++) { d_residbufs.push_back((gr_complex*)volk_malloc(d_fftsize*sizeof(gr_complex), @@ -101,6 +106,8 @@ namespace gr { buildwindow(); initialize(); + + set_trigger_mode(TRIG_MODE_FREE, 0, 0); } freq_sink_c_impl::~freq_sink_c_impl() @@ -114,6 +121,7 @@ namespace gr { } delete d_fft; volk_free(d_fbuf); + volk_free(d_tmpbuf); delete d_argv; } @@ -125,15 +133,6 @@ namespace gr { } void - freq_sink_c_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - unsigned int ninputs = ninput_items_required.size(); - for (unsigned int i = 0; i < ninputs; i++) { - ninput_items_required[i] = std::min(d_fftsize, 8191); - } - } - - void freq_sink_c_impl::initialize() { if(qApp != NULL) { @@ -162,6 +161,8 @@ namespace gr { if(d_name.size() > 0) set_title(d_name); + set_output_multiple(d_fftsize); + // initialize update time to 10 times a second set_update_time(0.1); } @@ -303,6 +304,29 @@ namespace gr { d_main_gui->resize(QSize(width, height)); } + void + freq_sink_c_impl::set_trigger_mode(trigger_mode mode, + float level, + int channel, + const std::string &tag_key) + { + gr::thread::scoped_lock lock(d_setlock); + + d_trigger_mode = mode; + d_trigger_level = level; + d_trigger_channel = channel; + d_trigger_tag_key = pmt::intern(tag_key); + d_triggered = false; + d_trigger_count = 0; + + d_main_gui->setTriggerMode(d_trigger_mode); + d_main_gui->setTriggerLevel(d_trigger_level); + d_main_gui->setTriggerChannel(d_trigger_channel); + d_main_gui->setTriggerTagKey(tag_key); + + _reset(); + } + std::string freq_sink_c_impl::title() { @@ -378,10 +402,26 @@ namespace gr { void freq_sink_c_impl::reset() { - d_index = 0; + gr::thread::scoped_lock lock(d_setlock); + _reset(); } void + freq_sink_c_impl::_reset() + { + d_trigger_count = 0; + + // Reset the trigger. + if(d_trigger_mode == TRIG_MODE_FREE) { + d_triggered = true; + } + else { + d_triggered = false; + } + } + + + void freq_sink_c_impl::fft(float *data_out, const gr_complex *data_in, int size) { if(d_window.size()) { @@ -398,15 +438,12 @@ namespace gr { size, 1.0, size); // Perform shift operation - unsigned int len = (unsigned int)(floor(size/2.0)); - float *tmp = (float*)malloc(sizeof(float)*len); - memcpy(tmp, &data_out[0], sizeof(float)*len); - memcpy(&data_out[0], &data_out[len], sizeof(float)*(size - len)); - memcpy(&data_out[size - len], tmp, sizeof(float)*len); - free(tmp); + memcpy(d_tmpbuf, &data_out[0], sizeof(float)*(d_tmpbuflen + 1)); + memcpy(&data_out[0], &data_out[size - d_tmpbuflen], sizeof(float)*(d_tmpbuflen)); + memcpy(&data_out[d_tmpbuflen], d_tmpbuf, sizeof(float)*(d_tmpbuflen + 1)); } - void + bool freq_sink_c_impl::windowreset() { gr::thread::scoped_lock lock(d_setlock); @@ -416,7 +453,9 @@ namespace gr { if(d_wintype != newwintype) { d_wintype = newwintype; buildwindow(); + return true; } + return false; } void @@ -428,7 +467,7 @@ namespace gr { } } - void + bool freq_sink_c_impl::fftresize() { gr::thread::scoped_lock lock(d_setlock); @@ -467,7 +506,19 @@ namespace gr { d_fbuf = (float*)volk_malloc(d_fftsize*sizeof(float), volk_get_alignment()); memset(d_fbuf, 0, d_fftsize*sizeof(float)); + + volk_free(d_tmpbuf); + d_tmpbuflen = (unsigned int)(floor(d_fftsize/2.0)); + d_tmpbuf = (float*)volk_malloc(sizeof(float)*(d_tmpbuflen + 1), + volk_get_alignment()); + + d_last_time = 0; + + set_output_multiple(d_fftsize); + + return true; } + return false; } void @@ -494,59 +545,121 @@ namespace gr { } } + void + freq_sink_c_impl::_gui_update_trigger() + { + trigger_mode new_trigger_mode = d_main_gui->getTriggerMode(); + d_trigger_level = d_main_gui->getTriggerLevel(); + d_trigger_channel = d_main_gui->getTriggerChannel(); + + std::string tagkey = d_main_gui->getTriggerTagKey(); + d_trigger_tag_key = pmt::intern(tagkey); + + if(new_trigger_mode != d_trigger_mode) { + d_trigger_mode = new_trigger_mode; + _reset(); + } + } + + void + freq_sink_c_impl::_test_trigger_tags(int start, int nitems) + { + uint64_t nr = nitems_read(d_trigger_channel); + std::vector<gr::tag_t> tags; + get_tags_in_range(tags, d_trigger_channel, + nr+start, nr+start+nitems, + d_trigger_tag_key); + if(tags.size() > 0) { + d_triggered = true; + d_index = tags[0].offset - nr; + d_trigger_count = 0; + } + } + + void + freq_sink_c_impl::_test_trigger_norm(int nitems, std::vector<double*> inputs) + { + const double *in = (const double*)inputs[d_trigger_channel]; + for(int i = 0; i < nitems; i++) { + d_trigger_count++; + + // Test if trigger has occurred based on the FFT magnitude and + // channel number. Test if any value is > the level (in dBx). + if(in[i] > d_trigger_level) { + d_triggered = true; + d_trigger_count = 0; + break; + } + } + + // If using auto trigger mode, trigger periodically even + // without a trigger event. + if((d_trigger_mode == TRIG_MODE_AUTO) && (d_trigger_count > d_fftsize)) { + d_triggered = true; + d_trigger_count = 0; + } + } + int freq_sink_c_impl::work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - int j=0; const gr_complex *in = (const gr_complex*)input_items[0]; // Update the FFT size from the application - fftresize(); - windowreset(); - check_clicked(); + bool updated = false; + updated |= fftresize(); + updated |= windowreset(); + if(updated) + return 0; - for(int i=0; i < noutput_items; i+=d_fftsize) { - unsigned int datasize = noutput_items - i; - unsigned int resid = d_fftsize-d_index; + check_clicked(); + _gui_update_trigger(); - // If we have enough input for one full FFT, do it - if(datasize >= resid) { + gr::thread::scoped_lock lock(d_setlock); + for(d_index = 0; d_index < noutput_items; d_index+=d_fftsize) { - if(gr::high_res_timer_now() - d_last_time > d_update_time) { - for(int n = 0; n < d_nconnections; n++) { - // Fill up residbuf with d_fftsize number of items - in = (const gr_complex*)input_items[n]; - memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*resid); + if((gr::high_res_timer_now() - d_last_time) > d_update_time) { - fft(d_fbuf, d_residbufs[n], d_fftsize); - for(int x = 0; x < d_fftsize; x++) { - d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]); - } - //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize); + // Trigger off tag, if active + if((d_trigger_mode == TRIG_MODE_TAG) && !d_triggered) { + _test_trigger_tags(d_index, d_fftsize); + if(d_triggered) { + // If not enough from tag position, early exit + if((d_index + d_fftsize) >= noutput_items) + return d_index; } + } - d_last_time = gr::high_res_timer_now(); - d_qApplication->postEvent(d_main_gui, - new FreqUpdateEvent(d_magbufs, d_fftsize)); - } + // Perform FFT and shift operations into d_magbufs + for(int n = 0; n < d_nconnections; n++) { + in = (const gr_complex*)input_items[n]; + memcpy(d_residbufs[n], &in[d_index], sizeof(gr_complex)*d_fftsize); - d_index = 0; - j += resid; - } - // Otherwise, copy what we received into the residbuf for next time - else { - for(int n = 0; n < d_nconnections; n++) { - in = (const gr_complex*)input_items[n]; - memcpy(d_residbufs[n]+d_index, &in[j], sizeof(gr_complex)*datasize); - } - d_index += datasize; - j += datasize; - } + fft(d_fbuf, d_residbufs[n], d_fftsize); + for(int x = 0; x < d_fftsize; x++) { + d_magbufs[n][x] = (double)((1.0-d_fftavg)*d_magbufs[n][x] + (d_fftavg)*d_fbuf[x]); + } + //volk_32f_convert_64f_a(d_magbufs[n], d_fbuf, d_fftsize); + } + + // Test trigger off signal power in d_magbufs + if((d_trigger_mode == TRIG_MODE_NORM) || (d_trigger_mode == TRIG_MODE_AUTO)) { + _test_trigger_norm(d_fftsize, d_magbufs); + } + + // If a trigger (FREE always triggers), plot and reset state + if(d_triggered) { + d_last_time = gr::high_res_timer_now(); + d_qApplication->postEvent(d_main_gui, + new FreqUpdateEvent(d_magbufs, d_fftsize)); + _reset(); + } + } } - return j; + return noutput_items; } } /* namespace qtgui */ |