#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# generated by wxGlade 0.3.5.1 on Fri Jun 10 10:32:01 2005

from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import audio
from gnuradio import usrp
from gnuradio import blks
from gnuradio import tv_rx
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import slider, powermate
from gnuradio.wxgui import stdgui, fftsink
from optparse import OptionParser
import sys
import math
import wx

ID_EXIT = wx.NewId()
ID_SLIDER_1 = wx.NewId()
ID_RADIO_FREQ = wx.NewId()
ID_RADIO_VOL = wx.NewId()
ID_GAUGE_1 = wx.NewId()
ID_SLIDER_1 = wx.NewId()


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        
        # Menu Bar
        self.frame_1_menubar = wx.MenuBar()
        self.SetMenuBar(self.frame_1_menubar)
        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(ID_EXIT, "Exit", "Exit", wx.ITEM_NORMAL)
        self.frame_1_menubar.Append(wxglade_tmp_menu, "File")
        # Menu Bar end
        self.panel_1 = wx.Panel(self, -1)
        self.label_2 = wx.StaticText(self, -1, "Frequency")
        self.bitmap_1 = wx.StaticBitmap(self, -1, wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/0.bmp", wx.BITMAP_TYPE_ANY))
        self.bitmap_2 = wx.StaticBitmap(self, -1, wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/9.bmp", wx.BITMAP_TYPE_ANY))
        self.bitmap_3 = wx.StaticBitmap(self, -1, wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/4.bmp", wx.BITMAP_TYPE_ANY))
        self.bitmap_4 = wx.StaticBitmap(self, -1, wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/5.bmp", wx.BITMAP_TYPE_ANY))
        self.radio_btn_1 = wx.RadioButton(self, -1, "frequency", style=wx.RB_GROUP)
        self.label_3 = wx.StaticText(self, -1, "Volume")
        self.gauge_1 = wx.Gauge(self, -1, 200)
        self.radio_btn_2 = wx.RadioButton(self, -1, "volume")
        self.label_1 = wx.StaticText(self, -1, "                    RF Gain      ")
        self.slider_1 = wx.Slider(self, ID_SLIDER_1, 0, 0, 115)

        # end wxGlade

	# wxpython gui events
        wx.EVT_MENU(self, ID_EXIT, self.MenuExit)
        wx.EVT_SLIDER(self, ID_SLIDER_1, self.set_gain)
        wx.EVT_RADIOBUTTON(self, ID_RADIO_FREQ, self.radio_button)
        wx.EVT_RADIOBUTTON(self, ID_RADIO_VOL, self.radio_button)

	# load pretty green numerals
        self.n0 = wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/0.bmp", wx.BITMAP_TYPE_ANY)
        self.n1 = wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/1.bmp", wx.BITMAP_TYPE_ANY)
        self.n2 = wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/2.bmp", wx.BITMAP_TYPE_ANY)
        self.n3 = wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/3.bmp", wx.BITMAP_TYPE_ANY)
        self.n4 = wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/4.bmp", wx.BITMAP_TYPE_ANY)
        self.n5 = wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/5.bmp", wx.BITMAP_TYPE_ANY)
        self.n6 = wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/6.bmp", wx.BITMAP_TYPE_ANY)
        self.n7 = wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/7.bmp", wx.BITMAP_TYPE_ANY)
        self.n8 = wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/8.bmp", wx.BITMAP_TYPE_ANY)
        self.n9 = wx.Bitmap("/usr/src/radio/wx/numerals/fancydigitalgreen/9.bmp", wx.BITMAP_TYPE_ANY)

# radio from tvrx_wfm_rcv_gui_pm.py
        self.fg = gr.flow_graph()
        self.vol = .1
        self.state = "FREQ"

        adc_rate = 64e6
        usrp_decim = 100
        usrp_rate = adc_rate / usrp_decim           # 640 kS/s
        chanfilt_decim = 2
        demod_rate = usrp_rate / chanfilt_decim
        audio_decimation = 10
        audio_rate = demod_rate / audio_decimation  # 32 kHz

        # usrp is data source
        src = usrp.source_c (0, usrp_decim)
        self.src = src

        dboards = (src.daughterboard_id(0),src.daughterboard_id(1))
        print dboards
        if dboards[0]==3:
            if dboards[1]==3:
                print "Which side?"
                sys.exit(0)
            else:
                which_side = 0
                which_type = 3
        elif dboards[1]==3:
            which_side = 1
            which_type = 3
        elif dboards[0]==1:
            if dboards[1]==1:
                print "Which side?"
                sys.exit(0)
            else:
                which_side = 0
                which_type = 1
        elif dboards[1]==1:
            which_side = 1
            which_type = 1
        else:
            print "No usable daughterboard found"
            sys.exit(0)

        if which_type == 3:
            dboard = tv_rx.tv_rx (src, which_side)
            self.dboard = dboard

        if which_side == 0:
            src.set_mux(gru.hexint(0xf0f0f0f0))
        else:
            src.set_mux(gru.hexint(0xf0f0f0f2))

        # set up frontend

        self.set_freq(94.5)

        chan_filt_coeffs = optfir.low_pass (1,      # gain
                                            usrp_rate,             # sampling rate
                                            80e3,   # passband cutoff
                                            115e3,   # stopband cutoff
                                            0.1,                 # passband ripple
                                            60)                  # stopband attenuation
        print len(chan_filt_coeffs)
        chan_filt = gr.fir_filter_ccf (chanfilt_decim,chan_filt_coeffs)

        # guts = blks.wfm_rcv (self, demod_rate, audio_decimation)
        quad_rate = demod_rate
        volume = 20.

        max_dev = 75e3
        fm_demod_gain = quad_rate/(2*math.pi*max_dev)
        audio_rate = quad_rate / audio_decimation


        # We assign to self so that outsiders can grab the demodulator
        # if they need to.  E.g., to plot its output.
        #
        # input: complex; output: float
        self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain)

        # input: float; output: float
        fs = demod_rate
        tau=75e-6
        w_p = 1/tau
        w_pp = math.tan (w_p / (fs * 2)) # prewarped analog freq

        a1 = (w_pp - 1)/(w_pp + 1)
        b0 = w_pp/(1 + w_pp)
        b1 = b0

        btaps = [b0, b1]
        ataps = [1, a1]

        if 0:
            print "btaps =", btaps
            print "ataps =", ataps
            global plot1
            plot1 = gru.gnuplot_freqz (gru.freqz (btaps, ataps), fs, True)

        self.deemph = gr.iir_filter_ffd(btaps, ataps)


        # compute FIR filter taps for audio filter
        width_of_transition_band = audio_rate / 32
        audio_coeffs = gr.firdes.low_pass (volume,         # gain
                                           quad_rate,      # sampling rate
                                           audio_rate/2 - width_of_transition_band,
                                           width_of_transition_band,
                                           gr.firdes.WIN_HAMMING)
        # input: float; output: float
        self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs)

        self.fg.connect (self.fm_demod, self.deemph, self.audio_filter)
# end hier_block

        volume_control = gr.multiply_const_ff(self.vol)
        self.volume_control = volume_control
        # sound card as final sink
        audio_sink = audio.sink (int (audio_rate))
	# audio_sink = gr.null_sink(gr.sizeof_float)

        # now wire it all together
        self.fg.connect (src, chan_filt)
        self.fg.connect (chan_filt, self.fm_demod)
        self.fg.connect (self.audio_filter, volume_control)
        self.fg.connect (volume_control, (audio_sink,0))

        self.slider_1.SetValue(55)
        self.set_gain(ID_SLIDER_1)
        self.gauge_1.SetValue(int(self.vol*200))
        if 1:
            pre_filt, fft_win1 = \
                       fftsink.make_fft_sink_c (self.fg, self.panel_1, "RF In", 512, usrp_rate)
            self.fg.connect (src, pre_filt)

        if 0:
            pre_demod, fft_win2 = \
                       fftsink.make_fft_sink_c (self, panel_1, "Channel Filter out", 512, demod_rate)
            self.fg.connect (chan_filt, pre_demod)

        if 0:
            post_deemph, fft_win3 = \
                         fftsink.make_fft_sink_f (self.fg, self.panel_1, "Deemph Out", 512, demod_rate, -60, 20)
            self.fg.connect (self.deemph, post_deemph)

        if 0:
            post_filt, fft_win4 = \
                       fftsink.make_fft_sink_f (self, panel_1, "Audio Out", 512, audio_rate, -60, 20)
            self.fg.connect (self.audio_filter, post_filt)

        try:
            self.knob = powermate.powermate(self)
            self.rot = 0
            powermate.EVT_POWERMATE_ROTATE (self, self.on_rotate)
            powermate.EVT_POWERMATE_BUTTON (self, self.on_button)
        except:
            print "No Powermate or Contour Knob found"
            sys.exit()

        self.__set_properties()
        self.__do_layout()

        self.fg.start()


    def __set_properties(self):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle("frame_1")
        self.label_1.SetSize((157, 25))
        self.slider_1.SetSize((200, 60))
        # end wxGlade

	# wxglade doesn't support FlexGridSizer - manually change
	# grid_sizer_1 back to wx.FlexGridSizer(3, 1, 0, 0) if edited
    def __do_layout(self):
        # begin wxGlade: MyFrame.__do_layout
        grid_sizer_1 = wx.FlexGridSizer(3, 1, 0, 0)
        sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
        grid_sizer_2 = wx.GridSizer(2, 3, 0, 0)
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
        grid_sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0)
        grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
        sizer_3.Add(self.bitmap_1, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
        sizer_3.Add(self.bitmap_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
        sizer_3.Add(self.bitmap_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
        sizer_3.Add(self.bitmap_4, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
        grid_sizer_2.Add(sizer_3, 1, wx.EXPAND, 0)
        grid_sizer_2.Add(self.radio_btn_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
        grid_sizer_2.Add(self.label_3, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
        grid_sizer_2.Add(self.gauge_1, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
        grid_sizer_2.Add(self.radio_btn_2, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
        grid_sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0)
        sizer_1.Add(self.label_1, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
        sizer_1.Add(self.slider_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
        grid_sizer_1.Add(sizer_1, 1, wx.EXPAND, 0)
        self.SetAutoLayout(True)
        self.SetSizer(grid_sizer_1)
        grid_sizer_1.Fit(self)
        grid_sizer_1.SetSizeHints(self)
        self.Layout()
        # end wxGlade

    def MenuExit(self, event):
        self.fg.stop()
        self.Close()

    def set_gain (self,event):
        gain = self.slider_1.GetValue()
        self.dboard.set_gain(gain)

    def on_rotate (self, event):
        self.rot += event.delta
        if (self.state == "FREQ"):
            if self.rot >= 3:
                self.set_freq(self.station + .2)
                self.update_display(self.station)
                self.rot -= 3
            elif self.rot <=-3:
                self.set_freq(self.station - .2)
                self.update_display(self.station)
                self.rot += 3
        else:
            if self.rot >= 3:
                self.set_vol(self.vol * 1.05)
                if self.vol < 1:
                  self.gauge_1.SetValue(int(self.vol*200))
                else:
                  self.gauge_1.SetValue(200)
                self.rot -= 3
            elif self.rot <=-3:
                self.set_vol(self.vol * .95)
                if self.vol < 1:
                  self.gauge_1.SetValue(int(self.vol*200))
                else:
                  self.gauge_1.SetValue(200)
                self.rot += 3

    def on_button (self, event):
        if event.value == 0:        # button up
            return
        self.rot = 0
        if self.state == "FREQ":
            self.state = "VOL"
            self.radio_btn_2.SetValue(True)
        else:
            self.state = "FREQ"
            self.radio_btn_1.SetValue(True)

    def set_freq (self, freq):
        if freq >878:
            freq = freq/10.0
        if freq < 87.9:
            freq = 87.9
        elif freq >108.1:
            freq = 108.1
        self.station = freq
        RF_freq = freq * 1e6
        (success, actual_freq) = self.dboard.set_freq(RF_freq)
        assert success
        IF_freq = RF_freq - actual_freq
        self.src.set_rx_freq (0, -IF_freq)

    def set_vol (self, vol):
        self.vol = vol
        self.volume_control.set_k(self.vol)

    def update_display(self, freq):
        n = int(freq * 10 + .000001) # needs a little help over the digit bound
        d = int(n/1e3)
        if d==0: self.bitmap_1.SetBitmap(self.n0)
        elif d==1: self.bitmap_1.SetBitmap(self.n1)
        elif d==2: self.bitmap_1.SetBitmap(self.n2)
        elif d==3: self.bitmap_1.SetBitmap(self.n3)
        elif d==4: self.bitmap_1.SetBitmap(self.n4)
        elif d==5: self.bitmap_1.SetBitmap(self.n5)
        elif d==6: self.bitmap_1.SetBitmap(self.n6)
        elif d==7: self.bitmap_1.SetBitmap(self.n7)
        elif d==8: self.bitmap_1.SetBitmap(self.n8)
        elif d==9: self.bitmap_1.SetBitmap(self.n9)
        n -= int(d*1e3)
        d = int(n/1e2)
        if d==0: self.bitmap_2.SetBitmap(self.n0)
        elif d==1: self.bitmap_2.SetBitmap(self.n1)
        elif d==2: self.bitmap_2.SetBitmap(self.n2)
        elif d==3: self.bitmap_2.SetBitmap(self.n3)
        elif d==4: self.bitmap_2.SetBitmap(self.n4)
        elif d==5: self.bitmap_2.SetBitmap(self.n5)
        elif d==6: self.bitmap_2.SetBitmap(self.n6)
        elif d==7: self.bitmap_2.SetBitmap(self.n7)
        elif d==8: self.bitmap_2.SetBitmap(self.n8)
        elif d==9: self.bitmap_2.SetBitmap(self.n9)
        n -= int(d*1e2)
        d = int(n/1e1)
        if d==0: self.bitmap_3.SetBitmap(self.n0)
        elif d==1: self.bitmap_3.SetBitmap(self.n1)
        elif d==2: self.bitmap_3.SetBitmap(self.n2)
        elif d==3: self.bitmap_3.SetBitmap(self.n3)
        elif d==4: self.bitmap_3.SetBitmap(self.n4)
        elif d==5: self.bitmap_3.SetBitmap(self.n5)
        elif d==6: self.bitmap_3.SetBitmap(self.n6)
        elif d==7: self.bitmap_3.SetBitmap(self.n7)
        elif d==8: self.bitmap_3.SetBitmap(self.n8)
        elif d==9: self.bitmap_3.SetBitmap(self.n9)
        n -= int(d*1e1)
        d = int(n/1e0)
        if d==0: self.bitmap_4.SetBitmap(self.n0)
        elif d==1: self.bitmap_4.SetBitmap(self.n1)
        elif d==2: self.bitmap_4.SetBitmap(self.n2)
        elif d==3: self.bitmap_4.SetBitmap(self.n3)
        elif d==4: self.bitmap_4.SetBitmap(self.n4)
        elif d==5: self.bitmap_4.SetBitmap(self.n5)
        elif d==6: self.bitmap_4.SetBitmap(self.n6)
        elif d==7: self.bitmap_4.SetBitmap(self.n7)
        elif d==8: self.bitmap_4.SetBitmap(self.n8)
        elif d==9: self.bitmap_4.SetBitmap(self.n9)

    def radio_button(self, event):
        id = event.GetId()
        if id == ID_RADIO_FREQ:
           self.state = "FREQ"
        if id == ID_RADIO_VOL:
           self.state = "VOL"



# end of class MyFrame

class MyApp(wx.App):
  def OnInit(self):
    frame = MyFrame(None, -1, "GNU FM Radio")
    frame.Show(True)
    self.SetTopWindow(frame)
    return True

app = MyApp(0)
app.MainLoop()

