discuss-gnuradio
[Top][All Lists]
Advanced

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

[Discuss-gnuradio] AM demodulation


From: Martin Dvh
Subject: [Discuss-gnuradio] AM demodulation
Date: Fri, 24 Dec 2004 17:59:31 +0100
User-agent: Mozilla Thunderbird 0.8 (X11/20040926)

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 ( );
};

reply via email to

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