>
>
> On Sat, Mar 28, 2009 at 9:27 AM, Karthik <karthik1...@gmail.com> wrote:
>
>> 2009/3/27 Mikhail Tadjikov <mtadji...@ucla.edu>
>>
>> Hello,
>>>
>>>  I'm trying to build several signal processing blocks for a project that
>>> I'm doing using USRP2.  I was going through the examples and sample code
>>> along with browsing the source code and I can't seem to find exactly what I
>>> need. I'm trying to do an average of a vector of length N:
>>>
>>> Input vector size N
>>> Output vector size 1
>>> I'm doing it for floats.
>>>
>>> ------------------------------
>>> #ifndef INCLUDED_CORES_WEIGHTED_AVG_FF_H
>>> #define INCLUDED_CORES_WEIGHTED_AVG_FF_H
>>> #include <gr_sync_block.h>
>>> class cores_weighted_avg_ff;
>>>
>>> typedef boost::shared_ptr<cores_weighted_avg_ff>
>>> cores_weighted_avg_ff_sptr;
>>> cores_weighted_avg_ff_sptr cores_make_weighted_avg_ff (unsigned int
>>> vlen);
>>>
>>> class cores_weighted_avg_ff : public gr_sync_block
>>> {
>>> private:
>>>    friend cores_weighted_avg_ff_sptr cores_make_weighted_avg_ff (unsigned
>>> int vlen);
>>>   cores_weighted_avg_ff (unsigned int vlen);      // private constructor
>>>   unsigned int d_vlen;
>>>
>>>  public:
>>>   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
>>>
>>> ----------------------------------------------------------------------------------------------------------
>>> and source
>>>
>>> -------------------------------------------------------------------------------------------
>>> #ifdef HAVE_CONFIG_H
>>> #include "config.h"
>>> #endif
>>> #include <cores_weighted_avg_ff.h>
>>> #include <gr_io_signature.h>
>>>
>>> cores_weighted_avg_ff_sptr
>>> cores_make_weighted_avg_ff (unsigned int vlen)
>>> {  return cores_weighted_avg_ff_sptr (new cores_weighted_avg_ff (vlen));}
>>>
>>> cores_weighted_avg_ff::cores_weighted_avg_ff (unsigned int vlen)
>>>   : gr_decimator_block ("weighed_avg_ff",
>>>                    gr_make_io_signature (1, 1, sizeof (float) * vlen),
>>>                    gr_make_io_signature (1, 1, sizeof (float))),
>>>     d_vlen(vlen)
>>> {
>>> }
>>> int
>>> cores_weighted_avg_ff::int 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];
>>>       float *out = (float *) output_items[0];
>>>       int noi = noutput_items * d_vlen;
>>>
>>>       for (int i = 0; i < noi; i++){
>>>         out += in[i]*i;
>>>       }
>>>       out /= d_vlen;
>>>       consume(noutput_items,d_vlen)
>>>
>>>       return noutput_items;
>>> }
>>>
>>> ------------------------------------------------------------------------------------------------
>>>
>>> I'm not sure if the code is correct what I want to do (input is more than
>>> welcome), when I compile this code I get a weird error:
>>> cores_weighted_avg_ff.h: In function ‘PyObject*
>>> _wrap_weighted_avg_ff(PyObject*, PyObject*)’:
>>> cores_weighted_avg_ff.h:63: error: too few arguments to function
>>> ‘cores_weighted_avg_ff_sptr cores_make_weighted_avg_ff(unsigned int)’
>>> cores.cc:4326: error: at this point in file
>>> make[4]: *** [cores.lo] Error 1
>>>
>>> Any help would be greatly appreciated.
>>
>>
>> With gr_sync_block you only need to write work() and not general_work().
>> The example at the end of this tutorial will be helpful
>> http://www.gnu.org/software/gnuradio/doc/howto-write-a-block.html. Also,
>> there is a "#endif" sitting in the middle of your code, it might be a typo.
>>
>> btw, if you are trying to get moving averages, there is a block already
>> available gr_moving_averages()
>>
>> Karthik
>>
>>
>>
> Thanks, but I'm trying to get weighted average specifically. I've looked at
> the code for moving_average... it's close to what I need, but its 1:1 in/out
> ratio, but I need N:1 ratio. That's the part I'm particular unclear about.
>

I have done something very similar in the past. I derive my block from
gr_sync_decimator to keep things simple. The value of 'N' is an input to the
block and is assumed to be constant. In the myblock_ff.h file define a
std::vector<float> d_buffer. in the myblock_ff.cc you will have a line such
as

myblock_ff::myblock_ff(int N) :
gr_sync_decimator("myblock",gr_io_sig...,gr_io_sig...,N)

Here, N sets the decimation factor. In the work() function, you loop over
all inputs and keep stuffing your inputs into d_buffer, using
d_buffer.push_back(). Once the length reaches N, you do your average or
other calculations, write an output and do d_buffer.clear(). This will work
even if your number of inputs is not a multiple of N since your buffer will
continue filling up from where you left the next time the work() function is
called.

I have attached the source from my code, but it has a lot going on in there
and isn't really commented. Line #152 in the .cc file does exactly what you
want to do, although in a different context. Hope this helps.

Karthik
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <afm_fft2_ff.h>
#include <gr_io_signature.h>
#include <math.h>

#ifndef min
#define min(X,Y) ((X) < (Y) ? : (X) , (Y))
#endif
#ifndef max
#define max(X,Y) ((X) > (Y) ? : (X) , (Y))
#endif


afm_fft2_ff_sptr afm_make_fft2_ff(int nfft, int naverages, float sampling_freq, float fundamental_freq, const std::vector<float> &freqs,const std::vector<float> &window)
{
    return afm_fft2_ff_sptr (new afm_fft2_ff(nfft,naverages,sampling_freq,fundamental_freq,freqs,window));
}

afm_fft2_ff::afm_fft2_ff(int nfft, int naverages, float sampling_freq, float fundamental_freq, const std::vector<float> &freqs, const std::vector<float> &window)
    : gr_sync_decimator("fft2_ff", 
	    gr_make_io_signature(3, 3, sizeof(float)),
	    gr_make_io_signature(1, 1, sizeof(float)),
	    (int) ceil(naverages*sampling_freq/(fundamental_freq*(2+freqs.size() ))) )
{
    d_nfft = nfft;
    d_fft_input = (double *) malloc(sizeof(double)*nfft);
    d_fft_out = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * (nfft/2 +1));
    d_plan = fftw_plan_dft_r2c_1d(nfft,d_fft_input, d_fft_out,FFTW_MEASURE); 

    d_naverages = naverages;
    d_window = window;
    d_freqs = freqs;
    DPRINTF(("Freq vector size = %d\n", d_freqs.size())); 
    d_sampling_freq = sampling_freq;
    d_fundamental_freq = fundamental_freq;
    d_bufferlen = (int) ceil(naverages*sampling_freq/fundamental_freq);
    d_buffer.reserve(d_bufferlen);
    d_buffer.clear();
    d_runonce = false;

    set_output_multiple((2+freqs.size()));
    //X,Y,freqs

    unsigned int i, index;
    for (i=0;i<d_freqs.size();i++){
	index = (int)round(d_freqs[i]*d_nfft/d_sampling_freq);
	DPRINTF(("Index for frequency%d = %d\n",i,index));
	try {
	    if (index > d_nfft/2)
		throw "Frequency must be less that 1/2 Sampling Frequency";
	}
	catch( char * str ) {
	    printf("Exception raised: %s\n",str);
	    exit(1);
	}
	d_freqs_index.push_back(index);
    }

    try {
	if(window.size() != nfft)
	    throw "Window size and nfft should be the same";
    }
    catch( char * str) {
	printf("Exception raised: %s\n",str);
	exit(1);
    }

    if( d_bufferlen > nfft)
	printf("\nWarning: Buffer length = %d, FFT length = %d. Signal will be truncated",d_bufferlen,nfft);

}

afm_fft2_ff::~afm_fft2_ff()
{
    fftw_destroy_plan(d_plan);
    fftw_free(d_fft_out);
    free(d_fft_input);
}

int afm_fft2_ff:: work(int noutput_items,
	gr_vector_const_void_star &input_items,
	gr_vector_void_star &output_items)

{
    /* chan[0] is signal
     * chan[1] X imaging signal
     * chan[2] Y imaging signal
     */
    int i, j, noutput_samples = 0; 
    const float * chan[3]; 
    float ** out = (float **) &output_items[0];
    for(i=0;i<3;i++)
        chan[i] = (const float *) input_items[i]; 

    if (d_runonce) {
	d_upordown = (chan[2][0] > 0) ? AFM_UP : AFM_DOWN;
	d_leftorright = (chan[1][0] > 0) ? AFM_LEFT : AFM_RIGHT;
	d_runonce = true;
    }

    for(i=0;i< noutput_items/(2+d_freqs.size());i++) {
	//stuff the buffer
	for(j=0;j<d_bufferlen;j++) 
	    d_buffer.push_back(chan[0][i*d_bufferlen + j]);
	
	//X imaging voltage
	if(d_leftorright == AFM_LEFT) {
	    if (chan[1][i*d_bufferlen] < 0)
		d_leftorright = AFM_RIGHT;
	}
	else {
	    if (chan[1][i*d_bufferlen] > 0.02)
		d_leftorright = AFM_LEFT;
	}
	out[0][noutput_samples] = (d_leftorright == AFM_LEFT) ? 1.0 : -1.0;
	noutput_samples++;

	//Y imaging voltage
	if(d_upordown == AFM_UP) {
	    if (chan[2][i*d_bufferlen] < 0)
		d_upordown = AFM_DOWN;
	}
	else {
	    if (chan[2][i*d_bufferlen] > 0.05)
		d_upordown = AFM_UP;
	}
	out[0][noutput_samples] = (d_upordown == AFM_DOWN) ? 1.0 : -1.0;
	noutput_samples++;

	noutput_samples = compute_params(out,noutput_samples);
	
	d_buffer.clear();
    }
    
    DPRINTF(("Outputs requested: %d, Output produced: %d, Input consumption(expected): %d, Input consumption(actual): %d\n",noutput_items,noutput_samples,
    (int) ceil(d_naverages*d_sampling_freq/(d_fundamental_freq*(2+d_freqs.size()))) * noutput_samples,
    noutput_items*d_bufferlen/(2+d_freqs.size())
    ));
    
    return noutput_samples;
}


int afm_fft2_ff:: compute_params(float ** out,int noutput_samples) {
    unsigned int i,index;
    float temp;
    if (d_bufferlen < d_nfft) {
	for (i=0;i<d_bufferlen;i++) 
	    d_fft_input[i] = (double) (d_buffer[i]*d_window[i]);
	for (;i<d_nfft;i++) 
	    d_fft_input[i] = 0; //zero-pad
   } 
    else {
	for (i=0;i<d_nfft;i++) 
	    d_fft_input[i] = (double) (d_buffer[i]*d_window[i]); //truncate after d_nfft
    }

    fftw_execute(d_plan);
    for(i=0;i<d_freqs.size();i++) {
	index = d_freqs_index[i];
	temp = (float) sqrt(d_fft_out[index][0]*d_fft_out[index][0] + d_fft_out[index][1]*d_fft_out[index][1]);
	out[0][noutput_samples] = temp;
	noutput_samples++;
    }
    return noutput_samples;
}



#ifndef INCLUDED_AFM_FFT2_FF_H
#define INCLUDED_AFM_FFT2_FF_H

#include <gr_sync_decimator.h>
#include "afm_trig_type.h"
#include <vector>
#include <complex.h>
#include <fftw3.h>

#define SILENT

#ifdef SILENT
#define DPRINTF(X)
#else
#define DPRINTF(X) printf X
#endif

class afm_fft2_ff;

typedef boost::shared_ptr<afm_fft2_ff> afm_fft2_ff_sptr;

afm_fft2_ff_sptr afm_make_fft2_ff(int nfft, int naverages, float sampling_freq, float fundamental_freq, const std::vector<float> &freqs,const std::vector<float> &window);

class afm_fft2_ff : public gr_sync_decimator
{
    private:
	friend afm_fft2_ff_sptr afm_make_fft2_ff(int nfft, int naverages, float sampling_freq, float fundamental_freq, const std::vector<float> &freqs,const std::vector<float> &window);
	
	afm_fft2_ff(int nfft, int naverages, float sampling_freq, float fundamental_freq, const std::vector<float> &freqs,const std::vector<float> &window);
	std::vector<float> d_buffer;

	int d_nfft;
	int d_naverages;
	double * d_fft_input;
	std::vector<float> d_window;
	std::vector<float> d_freqs;
	std::vector<int> d_freqs_index;
	float d_sampling_freq;
	float d_fundamental_freq;
	int d_bufferlen;

	fftw_complex *d_fft_out;
	fftw_plan d_plan;
	afm_direction_t d_upordown;
	afm_direction_t d_leftorright;
	bool d_runonce;
    public:
	~afm_fft2_ff();
    
	int work(int noutput_items, 
		gr_vector_const_void_star &input_items,
		gr_vector_void_star &output_items);
	
	int compute_params(float ** out,int noutput_samples);
};

#endif /* INCLUDED_AFM_FFT2_FF_H */

_______________________________________________
Discuss-gnuradio mailing list
Discuss-gnuradio@gnu.org
http://lists.gnu.org/mailman/listinfo/discuss-gnuradio

Reply via email to