Let me add just a quick comment on the' why'. Josh' transmitter was nearly DSB suppressed carrier.

The REASON for the DC offset is that the DC offset becomes the AM carrier after you heterodyne or mixer up to the operating frequency. Without the DC offset, you get DSB.

Now that Matt and I have added the complex carrier tracking PLL block, we will be able to build a synchronous AM detector shortly if Chuck does not get there first (which will be fine with me!). The difference in "rectify and filter" on AM broadcast and synchronous detection, where you remove the carrier to zero frequency and zero phase offset and then coherently add the two sidebands, is remarkable to listen to. HF shortwave broadcasts remain intelligible (though not necessarily great sounding) down close to the noise floor. The "overmodulation" from the carrier getting killed through selective fading just disappears and selective fading to one sideband is mostly covered up by the other. The closeness to the noise floor depends on your PLL loop bandwidth on the carrier removal.

One step after this would be a "Costas loop" recovery of DSB. It will not have the same noise performance as the SAM does since the transmitter is not wasting half its power sending carrier, but the sideband to noise ratio goes up enough to almost compensate. Matt and I started the PLL work doing a Costas loop but I think we detoured to a few other PLL based blocks before we got there. Last week seems like a blur now! If the Costas loop stuff is not there, I will try to get it in this coming week.


Bob


Chuck Swiger wrote:

At 12:56 PM 11/12/2005 -0500, you wrote:

Hey there,

I'm trying to create some simple transmitter programs as a basic
tutorial for myself, and I was wondering if someone would take a
quick look at my maximally simple AM transmitter program (just
trying to transmit a tone) and tell me where I've gone wrong.

Here's the program:

from gnuradio import gr
from gnuradio import audio
from gnuradio import usrp
from gnuradio.eng_option import eng_option

def build_graph ():
    fg = gr.flow_graph ()

    sampling_freq = 8000;
src1 = gr.sig_source_f ( sampling_freq, gr.GR_SIN_WAVE, 1090000, 4000000 )
    src2 = gr.sig_source_f ( sampling_freq, gr.GR_SIN_WAVE, 600, 14000 )
    dst = audio.sink (int (sampling_freq))
    mixer = gr.multiply_ff()
    fg.connect (src1, (mixer, 0))
    fg.connect (src2, (mixer, 1))
    f2c = gr.float_to_complex ()
    fg.connect ( mixer, ( f2c, 0 ) );
    usrp_interp = 400
    u = usrp.sink_c (0, usrp_interp)
    fg.connect(f2c, u)
    return fg

def main():
    fg = build_graph()
    fg.start()
    raw_input("Hit Enter to quit: ")
    fg.stop()

if __name__ == '__main__':
    main ()


Hi Josh - you almost have it. I've been wanting to work up an Am wireless broadcaster
as an updated version of this:

http://oak.cats.ohiou.edu/~postr/bapix/KnightWB.htm <http://oak.cats.ohiou.edu/%7Epostr/bapix/KnightWB.htm>

to play my own sound through old tube sets during the Christmas holidays.

A couple of points:  The sampling_freq in the script is way too low for
the frequency you're asking for in src1. Looks like you're aiming for 1090 on the AM dial so the sampling rate is going to need to be at least twice that per Nyquist. Plus you have to use a rate that, after usrp interpolation comes out 128Mhz. Also, to create an AM signal you mix an RF carrier with your AF plus a DC offset. Lastly - well, in the maximally simple script gr.float_to_complex() works since the usrp isn't doing any frequency shifting.

You can directly make low AM broadcast band signals using a sampling rate of 2Mhz
and usrp_interp of 64.   The maximally simple script that works for me is:

#!/usr/bin/env python


from gnuradio import gr
from gnuradio import usrp

def build_graph ():
    sampling_freq = 2e6

    fg = gr.flow_graph ()
src0 = gr.sig_source_f ( sampling_freq, gr.GR_SIN_WAVE, 560e3, 4000, 0 )
    src1 = gr.sig_source_f ( sampling_freq, gr.GR_SIN_WAVE, 440, .8, 1 )
    mixer = gr.multiply_ff ()
    dst = usrp.sink_c(0, 64)

    f2c = gr.float_to_complex()

    fg.connect ( src0, (mixer, 0) )
    fg.connect ( src1, (mixer, 1) )
    fg.connect ( mixer, f2c, dst )

    return fg

if __name__ == '__main__':
    fg = build_graph ()
    fg.start ()
    raw_input ('Press Enter to quit: ')
    fg.stop ()

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

Notice the 440hz audio tone has a DC offset=1. This actually works in my lab with a +10dbm amp and a tabletop am set. The amp has a 50ohm resistor load and a cliplead
dangling near the transistor set tuned to 560Khz.

The next script uses usrp frequency translation so it MUST use a Hilbert
filter to get from float to complex - otherwise you get unwanted spurious
output signals. Using usrp frequency shifting you can work at a lower sample
rate, but still create signals up to 1700Khz.

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


#!/usr/bin/env python
#
#                    AM generation
#
#                                       rf_loc
#                                         |
# [audio]--[scale]--[offset]---[lpf2c]---(x)-----> AM out
#                                      rf_mixc
#
#


from gnuradio import gr
from gnuradio import usrp
from gnuradio import audio_oss as audio
import sys

def build_graph ():

    usrp_interp = 80
    usrp_duc = 1050e3
    sink = usrp.sink_c (0, usrp_interp)
    print "requesting: ", usrp_duc, "hz"
    sink.set_tx_freq(0, usrp_duc)
# use usrp.tx_freq(0) to get actual freq, and use that
# to set rf_LO
    actual_freq = sink.tx_freq(0)
    print "got ", actual_freq, "hz"
    sink.set_nchannels(1)
    sink.set_mux(0x98)

    rf_LO = 40e3

    af_sample_rate = 32000
    rf_sample_rate = 1600000
    fir_interp = rf_sample_rate / af_sample_rate

    fg = gr.flow_graph ()

# transmit an audio file:
# audio_file = gr.file_source (gr.sizeof_short, "/usr/src/tests/usrp_tests/work_11.sw",0)
#    audio_conv = gr.short_to_float()
#    ascale = gr.multiply_const_ff(.00003)
#    src = gr.add_const_ff(1)
#    fg.connect(audio_file, audio_conv, ascale, src)

# microphone/line-in source:
#    src_mic = audio.source(af_sample_rate)
#    ascale = gr.multiply_const_ff(100)
#    src = gr.add_const_ff(1)
#    fg.connect (src_mic, src)

# dial-tone test:
    src1 = gr.sig_source_f (af_sample_rate,gr.GR_SIN_WAVE,440,.4,0)
    src2 = gr.sig_source_f (af_sample_rate,gr.GR_SIN_WAVE,350,.4,0)
    sum = gr.add_ff()
    src = gr.add_const_ff(1)
    fg.connect (src1, (sum, 0))
    fg.connect (src2, (sum, 1))
    fg.connect (sum, src)

    lpf2_taps = gr.firdes.low_pass ( \
           fir_interp, rf_sample_rate, 10e3, 10e3, gr.firdes.WIN_HAMMING)
    lpf2c = gr.interp_fir_filter_fff (fir_interp, lpf2_taps)

    rf_loc = gr.sig_source_f (rf_sample_rate,gr.GR_SIN_WAVE,rf_LO,2,0)

    rf_mixc = gr.multiply_ff ()

    scale = gr.multiply_const_ff(1e3)
    hilbert = gr.hilbert_fc(97)


    fg.connect (src, lpf2c)
    fg.connect (lpf2c, (rf_mixc, 0))
    fg.connect (rf_loc, (rf_mixc, 1))

    fg.connect (rf_mixc, scale)
    fg.connect (scale, hilbert)
    fg.connect (hilbert, sink)

    return fg

def main ():

    fg = build_graph ()

    fg.start ()
    raw_input ('Press Enter to quit: ')
    fg.stop ()

if __name__ == '__main__':
    main ()


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

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


--
Laziness is the number one inspiration for ingenuity.  Guilty as charged!



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

Reply via email to