def generate_padded_sync_words(self, f_min, f_max, preamble_length, rrcos=True):
        s1 = -1-1j
        s0 = -s1

        sync_word = [s0] * preamble_length + [s0, s1, s1, s1, s1, s0, s0, s0, s1, s0, s0, s1]
        sync_word_padded = []

        for bit in sync_word:
            sync_word_padded += [bit]
            sync_word_padded += [0] * (self._samples_per_symbol - 1)
        
        #rrcos = True
        if rrcos:
            filter = filters.rrcosfilter(161, 0.4, 1./self._symbols_per_second, self._sample_rate)[1]
            sync_word_padded_filtered = numpy.convolve(sync_word_padded, filter, 'full')
        else:
            filter = filters.rcosfilter(161, 0.4, 1./self._symbols_per_second, self._sample_rate)[1]
            sync_word_padded_filtered = sync_word_padded

        sync_words_shifted = {}

        for offset in range(f_min, f_max):
            shift_signal = numpy.exp(complex(0,-1)*numpy.arange(len(sync_word_padded_filtered))*2*numpy.pi*offset/float(self._sample_rate))
            sync_words_shifted[offset] = sync_word_padded_filtered * shift_signal
            sync_words_shifted[offset] = numpy.conjugate(sync_words_shifted[offset][::-1])
        
        return sync_words_shifted
    def __init__(self, center, input_sample_rate, search_depth=7e-3, search_window=50e3,
                    symbols_per_second=25000, verbose=False):

        self._center = center
        self._input_sample_rate = int(input_sample_rate)
        self._output_sample_rate = 500000

        if self._input_sample_rate % self._output_sample_rate:
            raise RuntimeError("Input sample rate must be a multiple of %d" % self._output_sample_rate)
            
        self._decimation = self._input_sample_rate / self._output_sample_rate

        self._search_depth = search_depth
        self._symbols_per_second = symbols_per_second
        self._output_samples_per_symbol = self._output_sample_rate/self._symbols_per_second
        self._verbose = verbose
        #self._verbose = True

        self._input_low_pass = scipy.signal.firwin(401, float(search_window)/self._input_sample_rate)
        self._low_pass2= scipy.signal.firwin(401, 10e3/self._output_sample_rate)
        self._rrc = filters.rrcosfilter(51, 0.4, 1./self._symbols_per_second, self._output_sample_rate)[1]

        self._sync_search = complex_sync_search.ComplexSyncSearch(self._output_sample_rate, verbose=self._verbose)

        self._pre_start_samples = int(0.1e-3 * self._output_sample_rate)

        if self._verbose:
            print 'input sample_rate', self._input_sample_rate
            print 'output sample_rate', self._output_sample_rate
Exemple #3
0
def main():
    print "\n","*"*80
    print "*** Python: Generate Root-Raised Cosine taps ***"
    if len(sys.argv) < 2:
        print "Exit: must enter the Length of the filter in samples"
        return
    elif len(sys.argv) < 3:
        print("Exit: must enter the roll-off factor Alpha in the range (0,1)")
        return
    elif len(sys.argv) < 4:
        print("Exit: must enter the symbol period Ts in seconds (1/baud_rate)")
        return
    elif len(sys.argv) < 5:
        print("Exit: must enter the sample rate Fs in Hertz")
        return
    elif len(sys.argv) < 6:
        print("Exit: must enter a value for the Maximum Tap")
        return
    elif len(sys.argv) < 7:
        print("Exit: must enter an output file")
        return

    length = int(sys.argv[1])
    alpha = float(sys.argv[2])
    if alpha <= 0.0 or alpha > 1.0:
        print("Exit: alpha out of range (0,1)")
        return
    Ts = float(sys.argv[3])
    Fs = float(sys.argv[4]);
    max_tap = int(sys.argv[5]);

    import filters
    time_idx, h_rrc = filters.rrcosfilter(length, alpha, Ts, Fs)
    #print time_idx
    #print h_rrc

    #set taps scale to integers
    scale = max(abs(h_rrc))
    print scale
    taps = (np.int16)(h_rrc * max_tap / scale)
    print taps
    print sum(taps)
    print (float)(sum(taps))/(float)(max_tap)
    #print taps[0:int(np.ceil(length/2.0))]

    fo = open(sys.argv[6], 'w')
    #print "\tName of the output file:", fo.name
    for i in taps[0:int(np.ceil(length/2.0))]:
        stringy = ''.join(str(i)+'\n')
        fo.write(stringy)
    fo.close()
Exemple #4
0
def main():
    print "\n","*"*80
    print "*** Python: Generate Root-Raised Cosine taps ***"
    if len(sys.argv) < 2:
        print "Exit: must enter the Length of the filter in samples"
        return
    elif len(sys.argv) < 3:
        print("Exit: must enter the roll-off factor Alpha in the range (0,1)")
        return
    elif len(sys.argv) < 4:
        print("Exit: must enter the symbol period Ts in seconds (1/baud_rate)")
        return
    elif len(sys.argv) < 5:
        print("Exit: must enter the sample rate Fs in Hertz")
        return
    elif len(sys.argv) < 6:
        print("Exit: must enter a value for the Maximum Tap")
        return
    elif len(sys.argv) < 7:
        print("Exit: must enter an output file")
        return

    length = int(sys.argv[1])
    alpha = float(sys.argv[2])
    if alpha <= 0.0 or alpha > 1.0:
        print("Exit: alpha out of range (0,1)")
        return
    Ts = float(sys.argv[3])
    Fs = float(sys.argv[4]);
    max_tap = int(sys.argv[5]);

    import filters
    time_idx, h_rrc = filters.rrcosfilter(length, alpha, Ts, Fs)
    #print time_idx
    #print h_rrc

    #set taps scale to integers
    scale = max(abs(h_rrc))
    print scale
    taps = (np.int16)(h_rrc * max_tap / scale)
    print taps
    print sum(taps)
    print (float)(sum(taps))/(float)(max_tap)
    #print taps[0:np.ceil(length/2.0)]

    fo = open(sys.argv[6], 'w')
    #print "\tName of the output file:", fo.name
    for i in taps[0:np.ceil(length/2.0)]:
        stringy = ''.join(str(i)+'\n')
        fo.write(stringy)
    fo.close()
    def generate_padded_sync_words(self,
                                   f_min,
                                   f_max,
                                   preamble_length,
                                   rrcos=True):
        s1 = -1 - 1j
        s0 = -s1

        sync_word = [s0] * preamble_length + [
            s0, s1, s1, s1, s1, s0, s0, s0, s1, s0, s0, s1
        ]
        sync_word_padded = []

        for bit in sync_word:
            sync_word_padded += [bit]
            sync_word_padded += [0] * (self._samples_per_symbol - 1)

        #rrcos = True
        if rrcos:
            filter = filters.rrcosfilter(161, 0.4,
                                         1. / self._symbols_per_second,
                                         self._sample_rate)[1]
            sync_word_padded_filtered = numpy.convolve(sync_word_padded,
                                                       filter, 'full')
        else:
            filter = filters.rcosfilter(161, 0.4,
                                        1. / self._symbols_per_second,
                                        self._sample_rate)[1]
            sync_word_padded_filtered = sync_word_padded

        sync_words_shifted = {}

        for offset in range(f_min, f_max):
            shift_signal = numpy.exp(
                complex(0, -1) * numpy.arange(len(sync_word_padded_filtered)) *
                2 * numpy.pi * offset / float(self._sample_rate))
            sync_words_shifted[
                offset] = sync_word_padded_filtered * shift_signal
            sync_words_shifted[offset] = numpy.conjugate(
                sync_words_shifted[offset][::-1])

        return sync_words_shifted
    def __init__(self,
                 center,
                 input_sample_rate,
                 search_depth=7e-3,
                 search_window=50e3,
                 symbols_per_second=25000,
                 verbose=False):

        self._center = center
        self._input_sample_rate = int(input_sample_rate)
        self._output_sample_rate = 500000

        if self._input_sample_rate % self._output_sample_rate:
            raise RuntimeError("Input sample rate must be a multiple of %d" %
                               self._output_sample_rate)

        self._decimation = self._input_sample_rate / self._output_sample_rate

        self._search_depth = search_depth
        self._symbols_per_second = symbols_per_second
        self._output_samples_per_symbol = self._output_sample_rate / self._symbols_per_second
        self._verbose = verbose
        #self._verbose = True

        self._input_low_pass = scipy.signal.firwin(
            401,
            float(search_window) / self._input_sample_rate)
        self._low_pass2 = scipy.signal.firwin(401,
                                              10e3 / self._output_sample_rate)
        self._rrc = filters.rrcosfilter(51, 0.4, 1. / self._symbols_per_second,
                                        self._output_sample_rate)[1]

        self._sync_search = complex_sync_search.ComplexSyncSearch(
            self._output_sample_rate, verbose=self._verbose)

        self._pre_start_samples = int(0.1e-3 * self._output_sample_rate)

        if self._verbose:
            print 'input sample_rate', self._input_sample_rate
            print 'output sample_rate', self._output_sample_rate
Exemple #7
0
def noise_vector(signal_power):
    n_var = signal_power * 10**(-SNR_dB / 10)  # calculate noise power
    w1 = np.random.normal(0, 1, N)  # complex gaussian noise
    w2 = np.random.normal(0, 1, N)
    w = ((np.sqrt(n_var / 2)) * (w1 + 1j * w2))
    return w


# In[5]:

alpha = 0.5  # Raised cosine (RRC) filter
Fs = 40000000
Ts = 0.000002
#Fs=40000;Ts=0.00005
time_idx, g = filters.rrcosfilter(N, alpha, Ts, Fs)
g = np.roll(g, N // 2)
#print("Filter Coefficients",g)

G, G_indices = GFDM_modulation_matrix(g)  # N x N
#G = threshold(G, e-16)
#print("G Indices", G_indices)

#print(np.linalg.det(G))
plt.plot(g)
plt.grid(True)
plt.show()

# In[6]:

    def cut_and_downmix(self, signal, search_offset=None, search_window=None, frequency_offset=0):
        #iq.write("/tmp/foo.cfile", signal)
        shift_signal = numpy.exp(complex(0,-1)*numpy.arange(len(signal))*2*numpy.pi*search_offset/float(self._input_sample_rate))
        signal_filtered = numpy.convolve(signal * shift_signal, self._input_low_pass, mode='same')
        #iq.write("/tmp/bar.cfile", signal_filtered)
        signal = signal_filtered[::self._decimation]
        #iq.write("/tmp/baz.cfile", signal)

        center = self._center + search_offset
        #print "new center:", center
        search_offset = 0

        if center + search_offset > 1626000000:
            preamble_length = 64
        else:
            preamble_length = 16

        self._fft_length = int(math.pow(2, int(math.log(self._output_samples_per_symbol*preamble_length,2))))
        self._fft_step = self._fft_length / 10
        if self._verbose:
            print 'fft_length', self._fft_length

        self._update_search_window(search_window)

        #signal_mag = [abs(x) for x in signal]
        #plt.plot(normalize(signal_mag))
        #begin, signal = self._signal_start(signal, search_offset)
        #t0 = time.time()
        begin = self._signal_start(signal[:int(self._search_depth * self._output_sample_rate)], search_offset)
        #print "_signal_start:", time.time() - t0

        if self._verbose:
            print 'begin', begin

        signal = signal[begin:]
        #t0 = time.time()
        preamble = signal[:self._fft_length]

        """
        preamble = signal[:self._fft_length]
        preamble_black = numpy.repeat(preamble * numpy.blackman(len(preamble)), 16)
        result = numpy.correlate(preamble_black, preamble_black, 'full')
        #result = numpy.correlate(signal, signal, 'full')
        result = numpy.angle(result[result.size/2:])
        print len(result)

        start_angle = result[0]
        count = 0
        if result[1] > 0:
            dir = 1
        else:
            dir = -1

 
        #for i in range(int(len(result) * 0.75)):
        for i in range(len(result)):
            if i == 0:
                continue

            if dir == 1:
                if result[i] > 0 and result[i-1] < 0:
                    count += 1
                    max_i = i
            else:
                if result[i] < 0 and result[i-1] > 0:
                    count += 1
                    max_i = i

        x0 = float(max_i - 1)
        x1 = float(max_i)
        y0 = result[max_i - 1]
        y1 = result[max_i]

        int_i = -y0 * (x1-x0)/(y1-y0) + x0

        guessed = dir * self._output_sample_rate / ((int_i)/float(count)) * 16
        print "guessed offset", guessed
        #plt.plot(result)
        #plt.show()
        """

        #signal = signal[:begin + self._fft_length/4]
        #preamble = signal[:self._fft_length]

        #plt.plot([begin+skip, begin+skip], [0, 1], 'r')
        #plt.plot([begin+skip+self._fft_length, begin+skip+self._fft_length], [0, 1], 'r')

        preamble = preamble * numpy.blackman(len(preamble))
        # Increase size of FFT to inrease resolution
        fft_result, fft_freq = self._fft(preamble, len(preamble) * 16)
        if self._verbose:
            print 'binsize', (fft_freq[101] - fft_freq[100]) * self._output_sample_rate

        # Use magnitude of FFT to detect maximum and correct the used bin
        mag = numpy.absolute(fft_result)
        max_index = numpy.argmax(mag)

        if self._verbose:
            print 'max_index', max_index
            print 'max_value', fft_result[max_index]
            print 'offset', fft_freq[max_index] * self._output_sample_rate

        #see http://www.dsprelated.com/dspbooks/sasp/Quadratic_Interpolation_Spectral_Peaks.html
        alpha = abs(fft_result[max_index-1])
        beta = abs(fft_result[max_index])
        gamma = abs(fft_result[max_index+1])
        correction = 0.5 * (alpha - gamma) / (alpha - 2*beta + gamma)
        real_index = max_index + correction

        #print "fft:", time.time() - t0

        #t0 = time.time()
        offset_freq = (fft_freq[math.floor(real_index)] + (real_index - math.floor(real_index)) * (fft_freq[math.floor(real_index) + 1] - fft_freq[math.floor(real_index)])) * self._output_sample_rate
        offset_freq+=frequency_offset

        if self._verbose:
            print 'correction', correction
            print 'corrected max', max_index - correction
            print 'corrected offset', offset_freq

            #print 'File:',basename,"f=%10.2f"%offset_freq

        #single_turn = self._output_sample_rate / offset_freq
        #offset_freq = guessed
        # Generate a complex signal at offset_freq Hz.
        shift_signal = numpy.exp(complex(0,-1)*numpy.arange(len(signal))*2*numpy.pi*offset_freq/float(self._output_sample_rate))

        # Multiply the two signals, effectively shifting signal by offset_freq
        signal = signal*shift_signal
        #print "shift:", time.time() - t0
        #t0 = time.time()

        #print "Sync word start after shift:", complex_sync_search.estimate_sync_word_start(signal, self._output_sample_rate)
        offset2, phase = self._sync_search.estimate_sync_word_freq(signal[:(preamble_length+16)*self._output_samples_per_symbol], preamble_length)
        offset2 = -offset2
        shift_signal = numpy.exp(complex(0,-1)*numpy.arange(len(signal))*2*numpy.pi*offset2/float(self._output_sample_rate))
        signal = signal*shift_signal
        #offset2 = complex_sync_search.estimate_sync_word_freq(signal[:32*self._output_samples_per_symbol], self._output_sample_rate)
        offset_freq += offset2
        #print "shift2:", time.time() - t0

        #plt.plot([cmath.phase(x) for x in signal[:self._fft_length]])
        if self._verbose:
            sin_avg = numpy.average(numpy.sin(numpy.angle(signal[:self._fft_length])))
            cos_avg = numpy.average(numpy.cos(numpy.angle(signal[:self._fft_length])))
            preamble_phase = math.atan2(sin_avg, cos_avg)
            print "Original preamble phase", math.degrees(preamble_phase)

        # Multiplying with a complex number on the unit circle
        # just changes the angle.
        # See http://www.mash.dept.shef.ac.uk/Resources/7_6multiplicationanddivisionpolarform.pdf
        #signal = signal * cmath.rect(1,math.pi/4 - preamble_phase)
        signal = signal * cmath.rect(1,-phase)

        #plt.plot([cmath.phase(x) for x in signal[:self._fft_length]])
        if self._verbose:
            sin_avg = numpy.average([math.sin(cmath.phase(x)) for x in signal[:self._fft_length]])
            cos_avg = numpy.average([math.cos(cmath.phase(x)) for x in signal[:self._fft_length]])
            preamble_phase = math.atan2(sin_avg, cos_avg)
            print "Corrected preamble phase", math.degrees(preamble_phase)

        #print numpy.average([x.real for x in signal[:self._fft_length]])
        #print numpy.average([x.imag for x in signal[:self._fft_length]])

        #print max(([abs(x.real) for x in signal]))
        #print max(([abs(x.imag) for x in signal]))

        ntaps= 161 # 10001, 1001, 161, 41
        ntaps= 2*int(self._output_sample_rate/20000)+1
        rrc = filters.rrcosfilter(ntaps, 0.4, 1./self._symbols_per_second, self._output_sample_rate)[1]
        signal = numpy.convolve(signal, rrc, 'same')

        #plt.plot([x.real for x in signal])
        #plt.plot([x.imag for x in signal])
        if self._verbose:
            print "preamble I avg",numpy.average(signal[:self._fft_length].real)
            print "preamble Q avg",numpy.average(signal[:self._fft_length].imag)

        #print max(([abs(x.real) for x in signal]))
        #print max(([abs(x.imag) for x in signal]))

        #plt.plot(numpy.absolute(fft_result))
        #plt.plot(fft_freq, numpy.absolute(fft_result))
        #plt.plot([], [bins[bin]], 'rs')
        #plt.plot(mag)
        #plt.plot(preamble)
        #plt.show()

        return (signal, center+offset_freq)
    def cut_and_downmix(self,
                        signal,
                        search_offset=None,
                        search_window=None,
                        frequency_offset=0):
        self._update_search_window(search_offset, search_window)

        #signal_mag = [abs(x) for x in signal]
        #plt.plot(normalize(signal_mag))
        begin = self._signal_start(signal)
        if self._verbose:
            print 'begin', begin

        # Skip a few samples to have a clean signal
        signal = signal[begin + self._skip:]
        preamble = signal[:self._fft_length]

        #plt.plot([begin+skip, begin+skip], [0, 1], 'r')
        #plt.plot([begin+skip+self._fft_length, begin+skip+self._fft_length], [0, 1], 'r')

        preamble = preamble * numpy.blackman(len(preamble))
        # Increase size of FFT to inrease resolution
        fft_result, fft_freq = self._fft(preamble, len(preamble) * 16)
        if self._verbose:
            print 'binsize', (fft_freq[100] -
                              fft_freq[101]) * self._sample_rate

        # Use magnitude of FFT to detect maximum and correct the used bin
        mag = numpy.absolute(fft_result)
        max_index = numpy.argmax(mag)

        if self._verbose:
            print 'max_index', max_index
            print 'max_value', fft_result[max_index]
            print 'offset', fft_freq[max_index] * self._sample_rate

        #see http://www.dsprelated.com/dspbooks/sasp/Quadratic_Interpolation_Spectral_Peaks.html
        alpha = abs(fft_result[max_index - 1])
        beta = abs(fft_result[max_index])
        gamma = abs(fft_result[max_index + 1])
        correction = 0.5 * (alpha - gamma) / (alpha - 2 * beta + gamma)
        real_index = max_index + correction

        offset_freq = (fft_freq[math.floor(real_index)] +
                       (real_index - math.floor(real_index)) *
                       (fft_freq[math.floor(real_index) + 1] -
                        fft_freq[math.floor(real_index)])) * self._sample_rate
        offset_freq += frequency_offset

        if self._verbose:
            print 'correction', correction
            print 'corrected max', max_index - correction
            print 'corrected offset', offset_freq

            #print 'File:',basename,"f=%10.2f"%offset_freq

        single_turn = self._sample_rate / offset_freq

        # Generate a complex signal at offset_freq Hz.
        shift_signal = numpy.exp(
            complex(0, -1) * numpy.arange(len(signal)) * 2 * numpy.pi *
            offset_freq / float(self._sample_rate))

        # Multiply the two signals, effectively shifting signal by offset_freq
        signal = signal * shift_signal

        #plt.plot([cmath.phase(x) for x in signal[:self._fft_length]])
        sin_avg = numpy.average(
            numpy.sin(numpy.angle(signal[:self._fft_length])))
        cos_avg = numpy.average(
            numpy.cos(numpy.angle(signal[:self._fft_length])))
        preamble_phase = math.atan2(sin_avg, cos_avg)
        if self._verbose:
            print "Original preamble phase", math.degrees(preamble_phase)

        # Multiplying with a complex number on the unit circle
        # just changes the angle.
        # See http://www.mash.dept.shef.ac.uk/Resources/7_6multiplicationanddivisionpolarform.pdf
        signal = signal * cmath.rect(1, math.pi / 4 - preamble_phase)

        #plt.plot([cmath.phase(x) for x in signal[:self._fft_length]])
        #sin_avg = numpy.average([math.sin(cmath.phase(x)) for x in signal[:self._fft_length]])
        #cos_avg = numpy.average([math.cos(cmath.phase(x)) for x in signal[:self._fft_length]])
        #preamble_phase = math.atan2(sin_avg, cos_avg)
        #print "Corrected preamble phase", math.degrees(preamble_phase)

        #print numpy.average([x.real for x in signal[:self._fft_length]])
        #print numpy.average([x.imag for x in signal[:self._fft_length]])

        #print max(([abs(x.real) for x in signal]))
        #print max(([abs(x.imag) for x in signal]))

        ntaps = 161  # 10001, 1001, 161, 41
        rrc = filters.rrcosfilter(ntaps, 0.4, 1. / self._symbols_per_second,
                                  self._sample_rate)[1]
        signal = numpy.convolve(signal, rrc, 'same')

        #plt.plot([x.real for x in signal])
        #plt.plot([x.imag for x in signal])
        if self._verbose:
            print "preamble I avg", numpy.average(
                signal[:self._fft_length].real)
            print "preamble Q avg", numpy.average(
                signal[:self._fft_length].imag)

        #print max(([abs(x.real) for x in signal]))
        #print max(([abs(x.imag) for x in signal]))

        #plt.plot(numpy.absolute(fft_result))
        #plt.plot(fft_freq, numpy.absolute(fft_result))
        #plt.plot([], [bins[bin]], 'rs')
        #plt.plot(mag)
        #plt.plot(preamble)
        #plt.show()

        return (signal, self._center + offset_freq)