def punctest(self, nc, np): length = 2046 # should be divisible by nc data = [random.randint(0, 255) for i in range(length)] # last K-1 bits are padding, meaning last byte is lost data[-1] = 0 data = tuple(data) src = gr.vector_source_b(data) enc = raw.conv_enc() dec = raw.conv_dec(length * 8) punc = raw.conv_punc(nc, np) depunc = raw.conv_punc(np, nc, 128) tofloat = gr.uchar_to_float() offset = gr.multiply_const_ff(255.0) touchar = gr.float_to_uchar() dst = gr.vector_sink_b() rx = gr.vector_sink_b() self.tb.connect(src, enc, punc, tofloat, offset, touchar, depunc, dec, dst) self.tb.connect(punc, rx) self.tb.run() rxlen = len(rx.data()) self.assertEqual(rxlen, (length * 8 * 2 * np) / nc) self.assertEqual(data, dst.data())
def test(self, ebno, data=None): random.seed(0) (nc, np) = self.puncparam # round number of bytes and symbols (FIXME, this is probably not always round) # one symbol = self.ncarriers * self.qambits * 0.5 * (np / nc) bits symbits = self.ncarriers * self.qambits * nc / (2. * np) #print "symbits = ", symbits assert int(self.nsymbols * symbits) % 8 == 0 length = int(self.nsymbols * symbits) / 8 # incl padding #print 'src: %d' % (length-1) #print 'pad: %d' % length #print 'fenc: %d' % (length * 8 * 2) #print 'punc: %f' % (length * 8 * 2. * np / nc) #print 'intrlv: %f' % ((length * 8 * 2. * np / nc) / (self.ncarriers*self.qambits)) #print 'total bits: %d' % (self.nframes * length * 8 * 2) if data is None: data = [ random.randint(0,255) for i in range((length-1)*self.nframes) ] data = tuple(data) src = gr.vector_source_b(data) #src = gr.file_source(gr.sizeof_char, "src1.datb"); dst = gr.vector_sink_b() fenc = raw.conv_enc() fdec = raw.conv_dec(length*8) punc = raw.conv_punc(nc, np) depunc = raw.conv_punc(np, nc, 128) pad = raw.conv_punc(length-1, length) depad = raw.conv_punc(length, length-1) intrlv = raw.intrlv_bit(self.ncarriers, self.qambits, False) deintrlv = raw.intrlv_bit(self.ncarriers, self.qambits, True) qenc = raw.qam_enc(self.qambits) qdec = raw.qam_dec(self.qambits) SNR = 10.0**(ebno/10.0) noise_power_in_channel = 1.0/SNR noise_voltage = math.sqrt(noise_power_in_channel/2.0) # AWGN only noise = gr.noise_source_c(gr.GR_GAUSSIAN, noise_voltage, 0) chan = gr.add_cc() self.tb.connect(noise, (chan, 1)) #chan = gr.channel_model(noise_voltage, 0.0, 1.0, [1.0, 0.0]), tofloat = gr.uchar_to_float() offset = gr.multiply_const_ff(255.0) touchar = gr.float_to_uchar() self.tb.connect(src, # length-1 pad, # length fenc, # 2*length punc, # 2*length*np/nc intrlv, # 2*length*np/nc (% ncarriers*qambits) qenc, # 2*length*np/nc / qambits (% ncarriers) chan, qdec, #tofloat, offset, touchar, deintrlv, depunc, fdec, depad, dst) #self.tb.connect(src, gr.file_sink(gr.sizeof_char, "src.datb")) #self.tb.connect(pad, gr.file_sink(gr.sizeof_char, "pad.datb")) #self.tb.connect(fenc, gr.file_sink(gr.sizeof_char, "fenc.datb")) #self.tb.connect(punc, gr.file_sink(gr.sizeof_char, "punc.datb")) #self.tb.connect(qenc, gr.file_sink(gr.sizeof_gr_complex, "qenc.dat")) #self.tb.connect(qdec, gr.file_sink(gr.sizeof_char, "qdec.datb")) #self.tb.connect(touchar, gr.file_sink(gr.sizeof_char, "qdec.datb")) #self.tb.connect(depunc, gr.file_sink(gr.sizeof_char, "depunc.datb")) #self.tb.connect(fdec, gr.file_sink(gr.sizeof_char, "fdec.datb")) #self.tb.connect(depad, gr.file_sink(gr.sizeof_char, "depad.datb")) self.tb.run() nerrors = 0 for (a,b) in itertools.izip(data, dst.data()): count = bitCount(a ^ b) nerrors += count ber = nerrors*1.0/len(data)/8 print "%d x %g @ %g dB\t#errors = %d\tBER = %g" % (self.qambits, nc/(2.0*np), ebno, nerrors, ber) return nerrors