error_rate.py

Go to the documentation of this file.
00001 # Copyright 2008 Free Software Foundation, Inc.
00002 # 
00003 # This file is part of GNU Radio
00004 # 
00005 # GNU Radio is free software; you can redistribute it and/or modify
00006 # it under the terms of the GNU General Public License as published by
00007 # the Free Software Foundation; either version 3, or (at your option)
00008 # any later version.
00009 # 
00010 # GNU Radio is distributed in the hope that it will be useful,
00011 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 # GNU General Public License for more details.
00014 # 
00015 # You should have received a copy of the GNU General Public License
00016 # along with GNU Radio; see the file COPYING.  If not, write to
00017 # the Free Software Foundation, Inc., 51 Franklin Street,
00018 # Boston, MA 02110-1301, USA.
00019 # 
00020 
00021 default_win_size = 1000
00022 
00023 from gnuradio import gr
00024 import gnuradio.gr.gr_threading as _threading
00025 import numpy
00026 
00027 #generate 1s counts array
00028 _1s_counts = [sum([1&(i>>j) for j in range(8)]) for i in range(2**8)]
00029 
00030 class input_watcher(_threading.Thread):
00031         """
00032         Read samples from the message queue and hand them to the callback.
00033         """
00034         
00035         def __init__(self, msgq, callback):
00036                 self._msgq = msgq
00037                 self._callback = callback
00038                 _threading.Thread.__init__(self)
00039                 self.setDaemon(1)
00040                 self.keep_running = True
00041                 self.start()
00042                 
00043         def run(self):
00044                 r = ''
00045                 while True:
00046                         msg = self._msgq.delete_head()
00047                         itemsize = int(msg.arg1())
00048                         nitems = int(msg.arg2())
00049                         s = r + msg.to_string()
00050                         i = (nitems-nitems%2)*itemsize
00051                         r = s[i:]
00052                         s = s[:i]                       
00053                         samples = numpy.fromstring(s, numpy.int8)
00054                         self._callback(samples)         
00055                 
00056 class error_rate(gr.hier_block2):
00057         """
00058         Sample the incoming data streams (byte) and calculate the bit or symbol error rate.
00059         Write the running rate to the output data stream (float).
00060         """
00061         
00062         def __init__(self, type='BER', win_size=default_win_size, bits_per_symbol=2):   
00063                 """!
00064                 Error rate constructor.
00065                 @param type a string 'BER' or 'SER'
00066                 @param win_size the number of samples to calculate over
00067                 @param bits_per_symbol the number of information bits per symbol (BER only)
00068                 """     
00069                 #init
00070                 gr.hier_block2.__init__(
00071                         self, 'error_rate', 
00072                         gr.io_signature(2, 2, gr.sizeof_char), 
00073                         gr.io_signature(1, 1, gr.sizeof_float),
00074                 )
00075                 assert type in ('BER', 'SER')
00076                 self._max_samples = win_size
00077                 self._bits_per_symbol = bits_per_symbol
00078                 #setup message queue
00079                 msg_source = gr.message_source(gr.sizeof_float, 1)
00080                 self._msgq_source = msg_source.msgq()
00081                 msgq_sink = gr.msg_queue(2)
00082                 msg_sink = gr.message_sink(gr.sizeof_char, msgq_sink, False) #False -> blocking
00083                 inter = gr.interleave(gr.sizeof_char)
00084                 #start thread
00085                 self._num_errs = 0
00086                 self._err_index = 0
00087                 self._num_samps = 0
00088                 self._err_array = numpy.zeros(self._max_samples, numpy.int8)
00089                 if type == 'BER':
00090                         input_watcher(msgq_sink, self._handler_ber)
00091                 elif type == 'SER':
00092                         input_watcher(msgq_sink, self._handler_ser)
00093                 #connect
00094                 self.connect(msg_source, self)
00095                 self.connect((self, 0), (inter, 0))
00096                 self.connect((self, 1), (inter, 1))
00097                 self.connect(inter, msg_sink)
00098                 
00099         def _handler_ber(self, samples):
00100                 num = len(samples)/2
00101                 arr = numpy.zeros(num, numpy.float32)
00102                 for i in range(num):
00103                         old_err = self._err_array[self._err_index]                                                                      
00104                         #record error
00105                         self._err_array[self._err_index] = _1s_counts[samples[i*2] ^ samples[i*2 + 1]]
00106                         self._num_errs = self._num_errs + self._err_array[self._err_index] - old_err
00107                         #increment index
00108                         self._err_index = (self._err_index + 1)%self._max_samples
00109                         self._num_samps = min(self._num_samps + 1, self._max_samples)
00110                         #write sample
00111                         arr[i] = float(self._num_errs)/float(self._num_samps*self._bits_per_symbol)
00112                 #write message
00113                 msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, num)
00114                 self._msgq_source.insert_tail(msg)                      
00115                 
00116         def _handler_ser(self, samples):
00117                 num = len(samples)/2
00118                 arr = numpy.zeros(num, numpy.float32)
00119                 for i in range(num):
00120                         old_err = self._err_array[self._err_index]                                                                      
00121                         #record error
00122                         ref = samples[i*2]
00123                         res = samples[i*2 + 1]
00124                         if ref == res:
00125                                 self._err_array[self._err_index] = 0
00126                         else:
00127                                 self._err_array[self._err_index] = 1
00128                         #update number of errors
00129                         self._num_errs = self._num_errs + self._err_array[self._err_index] - old_err
00130                         #increment index
00131                         self._err_index = (self._err_index + 1)%self._max_samples
00132                         self._num_samps = min(self._num_samps + 1, self._max_samples)
00133                         #write sample
00134                         arr[i] = float(self._num_errs)/float(self._num_samps)
00135                 #write message
00136                 msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, num)
00137                 self._msgq_source.insert_tail(msg)              
00138                 

Generated on Sat Aug 23 02:00:11 2008 for GNU Radio Companion by  doxygen 1.5.4