discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnuradio] AM demodulation


From: David Carr
Subject: Re: [Discuss-gnuradio] AM demodulation
Date: Fri, 24 Dec 2004 16:00:12 -0600
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040928 MultiZilla/1.6.4.0b

Martin,

One approach you might consider is the one below:

Data->IQ demodulator->gr_complex_to_mag->low pass...

All of these components are already implemented and should work.
When I get a chance I'll test some the code you posted. On a cursory glance though, this stikes me. What is your signal source? If its the AM broadcast band the filters below might be a bit too wide. As a reference the entire (mid) AM broadcast band is about 1.1MHz wide and the stations themselves
are only 10KHz wide.

Hope this helps,
David Carr

Martin Dvh wrote:

I am trying to build an AM receiver with gnuradio.
Can anybody tell me how to do this (example)?

So far I found and did the following:
In the WIKI I find that building an AM detector "is easy", but not how to do it. On the mailinglist archive I found that using an absolute value followed by a low-pass filter should do the job. The current version of gnuradio has no absolute value block so I build a gr_abs_cc block.
I also tried using the gr_mult functionality.
(Multiply the signal with itsself, this gives a squared value which should also do for AM)

The multiply with itsself does seem to work although it is quite an processorintensive option. The abs value works "sort of", maybe I got the values for the low-pass filter or the decimation wrong (I used some settings of the FMdemod example) I get a high beep through every signal (even if there is no signal, just noise)

Has anybody any experience with AM reception using gnuradio and what did You use.

attached is the gr_abs_cc I build, and the am_receiver.py which uses it.

It takes the absolute value of a complex signal. The absolute value of a float signal would be much less processor intensive but I have not build that yet.

The relevant part in my AM_receiver.py
(input is 50 Msps followed by a channel filter and decimator (decimate by 512)

def build_pipeline (fg, quad_rate, audio_decimation):
    '''Given a flow_graph, fg, construct a pipeline
    for demodulating a narrowband AM signal.  The
    input is the downconverteed complex baseband
    signal. The output is the demodulated audio.

    build_pipeline returns a two element tuple
    containing the input and output endpoints.
    '''
    audio_rate = quad_rate / audio_decimation

    # input: complex; output: float
    # fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain)
    # HERE IS THE DEMODULATOR:
    am_demod = gr.abs_cf()
    # compute FIR filter taps for audio filter
    width_of_transition_band = audio_rate / 32
    audio_coeffs = \
      gr.firdes.low_pass (
        1.0,            # gain
        quad_rate,      # sampling rate
        audio_rate/2 - width_of_transition_band,
        width_of_transition_band,
        gr.firdes.WIN_HAMMING)

    # input: float; output: float
    audio_filter =  gr.fir_filter_fff (audio_decimation,
                         audio_coeffs)

    fg.connect (am_demod, audio_filter)
    return ((am_demod, 0), (audio_filter, 0))


------------------------------------------------------------------------

#!/usr/bin/env python

import math

from gnuradio import gr
from gnuradio import audio
import sys
from gnuradio import mc4020
from gnuradio import v4ltuner
def high_speed_adc (fg, input_rate): #My own driver for my own hacked bttv card 
to have functionality similar to mc4020, ofcourse you can use your own high 
speed ADC source or a software generated signal
   return mc4020.source (input_rate,mc4020.BTTV_EXTEND_RAW_LINES  | mc4020.BTTV_NOGAP, 
"/dev/video0");

# return a gr.flow_graph
#
def build_chan_filter(freq,input_rate,cfir_decimation):
  # compute FIR filter taps for channel selection
   channel_coeffs = \
     gr.firdes.low_pass (
       1.0,          # gain
       input_rate,   # sampling rate
       250e3, #250e3,        low pass cutoff freq
       1e6,#800e3, #8*100e3,       width of trans. band
       gr.firdes.WIN_HAMMING)

   # input: short; output: complex
   chan_filter1 = \
     gr.freq_xlating_fir_filter_scf (
       cfir_decimation,
       channel_coeffs,
       freq,        # 1st station freq
       input_rate)
   return chan_filter1

def build_graph (src,freq1, 
input_rate,cfir_decimation,audio_decimation,chan_filter1):

   quad_rate = input_rate / cfir_decimation
   audio_rate =  quad_rate / audio_decimation
(head1, tail1) = \
     build_pipeline (fg, quad_rate,
                     audio_decimation)
# sound card as final sink
   audio_sink = audio.sink (int (audio_rate))
# now wire it all together
   fg.connect (src, chan_filter1)
   fg.connect (chan_filter1, head1)
   fg.connect (tail1, (audio_sink, 0))
return fg

def build_pipeline (fg, quad_rate, audio_decimation):
   '''Given a flow_graph, fg, construct a pipeline
   for demodulating a broadcast FM signal.  The
   input is the downconverteed complex baseband
   signal. The output is the demodulated audio.

   build_pipeline returns a two element tuple
   containing the input and output endpoints.
   '''
   # fm_demod_gain = 2200.0/32768.0
   audio_rate = quad_rate / audio_decimation
   # volume = 2.0

   # input: complex; output: float
   #fm_demod = \
   #  gr.quadrature_demod_cf (volume*fm_demod_gain)

   # HERE IS THE AM DEMODULATOR:
   am_demod = gr.abs_cf()

   # compute FIR filter taps for audio filter
   width_of_transition_band = audio_rate / 32
   audio_coeffs = \
     gr.firdes.low_pass (
       1.0,            # gain
       quad_rate,      # sampling rate
       audio_rate/2 - width_of_transition_band,
       width_of_transition_band,
       gr.firdes.WIN_HAMMING)

   # input: float; output: float
   audio_filter = \
     gr.fir_filter_fff (audio_decimation,
                        audio_coeffs)

   fg.connect (am_demod, audio_filter)
   return ((am_demod, 0), (audio_filter, 0))
if __name__ == '__main__':
#f1 = float (sys.argv[1:][0]) nargs = len (sys.argv[1:])
   #freq1 = IFfreq
   #tunerfreq = RFfreq
   if nargs == 1:
       freq1 = float (sys.argv[1:][0]) * 1e6
   elif nargs == 2:
       freq1 = float (sys.argv[1:][0]) * 1e6
       tunerfreq=float (sys.argv[1:][1]) * 1e6
   else:
       sys.stderr.write ('usage: am_receiver.py  IFfreq RFfreq\n')
       sys.stderr.write ('frequencies in MHz\n')
       sys.exit (1)

   input_rate=int(50000000)  #50 Msps    # int(50000000.0 * 
674*1024*50/35468950)
   rate_fact = 1.0                   # (674.0*1024*50)/35468950
   #orig FM cfir_decimation = 125
   #orig FM audio_decimation = 5
   cfir_decimation = 512
   audio_decimation = 8

   fg = gr.flow_graph ()
# use high speed ADC as input source
   src = high_speed_adc (fg, input_rate)

   
chan_filter1=build_chan_filter(int(freq1*rate_fact),input_rate,cfir_decimation)
   
fg2=build_graph(src,freq1*rate_fact,input_rate,cfir_decimation,audio_decimation,chan_filter1)
   actualtunerfreq=src.set_RF_freq(tunerfreq)
   freq1=freq1+(tunerfreq - actualtunerfreq)
   print(tunerfreq);
   print(actualtunerfreq);
   print(freq1);
   letter=""
fg2.start () # fork thread(s) and return while (letter!="x"):
       #print(freq1)
        letter=raw_input ( 'Press x Enter to quit: ')
if letter=="'": tunerfreq+=100000 elif letter==";": tunerfreq-=100000 elif letter==">": tunerfreq+=10000 elif letter=="<": tunerfreq-=10000 elif letter==".": tunerfreq+=1000 elif letter==",": tunerfreq-=1000 else: tunerfreq+=10000
        print(tunerfreq)
       print(src.set_RF_freq(tunerfreq))
#chan_filter1.set_center_freq( int(freq1*rate_fact) ) fg2.stop ()
   print "The end!"

------------------------------------------------------------------------

/* -*- 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.
*/

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

#include <gr_abs_cf.h>
#include <gr_io_signature.h>

gr_abs_cf::gr_abs_cf ():
gr_sync_block ("abs_cf",
               gr_make_io_signature (1, 1, sizeof (gr_complex)),
               gr_make_io_signature (1, 1, sizeof (float)))
{
}

gr_abs_cf_sptr
gr_make_abs_cf ()
{
        return gr_abs_cf_sptr (new gr_abs_cf ());
}

int
gr_abs_cf::work (int noutput_items,
                     gr_vector_const_void_star & input_items,
                     gr_vector_void_star & output_items)
{
        gr_complex *in = (gr_complex *) input_items[0];
float *out = (float *) output_items[0]; int i;
        for ( i = 0; i < noutput_items-3; i+=4)//stride=4
        {
                out[i] = abs (in[i]);
                out[i+1]=abs (in[i+1]);
                out[i+2]=abs (in[i+2]);
                out[i+3]=abs (in[i+3]);
        }
        for (; i < noutput_items; i++) //tail section
        {
                out[i] = abs (in[i]);
        }
        return noutput_items;
}
------------------------------------------------------------------------

/* -*- 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_GR_ABS_CF_H
#define INCLUDED_GR_ABS_CF_H

#include <gr_sync_block.h>

class gr_abs_cf;
typedef
        boost::shared_ptr <
        gr_abs_cf >
        gr_abs_cf_sptr;
gr_abs_cf_sptr
gr_make_abs_cf ();

/*!
* \brief abs: compute absolute value, can be used for envelope AM demodulator: 
complex in, complex out
* \ingroup block
*/
class
        gr_abs_cf:
        public
        gr_sync_block
{
        friend gr_abs_cf_sptr
        gr_make_abs_cf ();
        gr_abs_cf ();
        
     public:
        int
        work (int noutput_items,
              gr_vector_const_void_star & input_items,
              gr_vector_void_star & output_items);
};

#endif /* INCLUDED_GR_ABS_CF_H */
------------------------------------------------------------------------

/* -*- 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.
*/

GR_SWIG_BLOCK_MAGIC (gr, abs_cf)

gr_abs_cf_sptr gr_make_abs_cf ( );

class gr_abs_cf : public gr_sync_block
{
 gr_abs_cf ( );
};
------------------------------------------------------------------------

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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]