00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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)
00083 inter = gr.interleave(gr.sizeof_char)
00084
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
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
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
00108 self._err_index = (self._err_index + 1)%self._max_samples
00109 self._num_samps = min(self._num_samps + 1, self._max_samples)
00110
00111 arr[i] = float(self._num_errs)/float(self._num_samps*self._bits_per_symbol)
00112
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
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
00129 self._num_errs = self._num_errs + self._err_array[self._err_index] - old_err
00130
00131 self._err_index = (self._err_index + 1)%self._max_samples
00132 self._num_samps = min(self._num_samps + 1, self._max_samples)
00133
00134 arr[i] = float(self._num_errs)/float(self._num_samps)
00135
00136 msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, num)
00137 self._msgq_source.insert_tail(msg)
00138