Пример #1
0
    def process_file(self, file_name):
        b, a = self.butter_lowpass(100e3, 1e6)

        with open(file_name, "rb") as f:
            f.read(self._struct_len)
            while True:
                data = f.read(self._struct_len)
                if not data: break
                if len(data) != self._struct_len: break

                slice = numpy.frombuffer(data, dtype=self._struct_elem)
                if self._struct_elem == numpy.uint8:
                    slice = slice.astype(numpy.float32) # convert to float
                    slice = (slice-127.35)/128.             # Normalize
                    slice = slice.view(numpy.complex64) # reinterpret as complex
 
                # Multiply the two signals, effectively shifting signal by offset_freq
                slice = slice*self._shift_signal
                #slice = self._shift_signal
                slice = scipy.signal.lfilter(b, a, slice)
                slice = scipy.signal.decimate(slice, 4)
                #slice = slice[::4]
                
                #slice = self._shift_signal
                iq.write(sys.stdout, slice)
 def process_one(basename, time_stamp, signal_strength, bin_index, freq, signal):
     mix_signal, mix_freq = cad.cut_and_downmix(signal=signal, search_offset=freq, search_window=search_window)
     dataarray, data, access_ok, lead_out_ok, confidence, level, nsymbols = dem.demod(mix_signal)
     msg = "RAW: %s %09d %010d A:%s L:%s %3d%% %.3f %3d %s"%(basename,time_stamp,mix_freq,("no","OK")[access_ok],("no","OK")[lead_out_ok],confidence,level,(nsymbols-12),data)
     out_queue.put(msg)
     if mix_freq < 1626e6 and confidence>95 and nsymbols>40 and access_ok==1:
         iq.write("keep.%010d-f%010d.raw"%(time_stamp,freq),signal)
Пример #3
0
 def process_one(basename, time_stamp, signal_strength, bin_index, freq,
                 signal):
     mix_signal, mix_freq = cad.cut_and_downmix(signal=signal,
                                                search_offset=freq,
                                                search_window=search_window)
     dataarray, data, access_ok, lead_out_ok, confidence, level, nsymbols = dem.demod(
         mix_signal)
     msg = "RAW: %s %09d %010d A:%s L:%s %3d%% %.3f %3d %s" % (
         basename, time_stamp, mix_freq, ("no", "OK")[access_ok],
         ("no", "OK")[lead_out_ok], confidence, level,
         (nsymbols - 12), data)
     out_queue.put(msg)
     if mix_freq < 1626e6 and confidence > 95 and nsymbols > 40 and access_ok == 1:
         iq.write("keep.%010d-f%010d.raw" % (time_stamp, freq), signal)
Пример #4
0
        print "CP length", dp.cp_length
        cycled_prs = numpy.concatenate((ifft_prs[-dp.cp_length:], ifft_prs))
        return cycled_prs
    else:
        return ifft_prs

    #print cycled_prs
    #print len(cycled_prs)


if __name__ == "__main__":

    #sample_rate = 2048000
    sample_rate = 2000000
    cycled_prs = modulate_prs(sample_rate)
    iq.write("/tmp/generated.cfile", cycled_prs)

    signal = numpy.concatenate(([0] * 2048, cycled_prs))
    #signal = numpy.concatenate(([0] * 2048, cycled_prs, [0] * 2048, cycled_prs))
    #signal = numpy.concatenate(([0] * 2048, prs, [0] * 2048, prs))

    iq.write("/tmp/foo.cfile", signal)
    #print dp.frequency_interleaving_sequence_array

    dp = parameters.dab_parameters(1, sample_rate)
    Tu = dp.fft_length

    offset = 600
    shift_signal = numpy.exp(
        complex(0, -1) * numpy.arange(len(signal)) * 2 * numpy.pi * offset /
        float(sample_rate))
Пример #5
0
              verbose=verbose,
              debug=debug)

    dataarray, data, access_ok, lead_out_ok, confidence, level, nsymbols = d.demod(
        signal)

    print "RAW: %s %07d %010d A:%s L:%s %3d%% %.3f %3d %s" % (
        rawfile, timestamp, freq, ("no", "OK")[access_ok],
        ("no", "OK")[lead_out_ok], confidence, level, (nsymbols - 12), data)

    if 0:  # Create r / phi file
        with open("%s.rphi" % (os.path.basename(basename)), 'wb') as out:
            signal = [
                item for sample in signal
                for item in [abs(sample), cmath.phase(sample)]
            ]
            s = "<" + len(signal) * 'f'
            out.write(struct.Struct(s).pack(*signal))

    if debug:  # The graphical debugging file
        iq.write("%s.peaks" % (os.path.basename(basename)), d.peaks)

    if 0:  # The actual samples we used
        iq.write("%s.samples" % (os.path.basename(basename)),
                 mynormalize(d.samples))

    if 0:  # The data bitstream
        with open("%s.data" % (os.path.basename(basename)), 'wb') as out:
            for c in dataarray:
                out.write(chr(c))
            frequency_offset = float(arg)
        elif opt in ('-v', '--verbose'):
            verbose = True
        elif opt in ('-d', '--decimation'):
            decimation = int(arg)
            print "deci:",decimation

    if sample_rate == None:
        print >> sys.stderr, "Sample rate missing!"
        exit(1)
    if center == None:
        print >> sys.stderr, "Need to specify center frequency!"
        exit(1)

    if len(remainder)==0:
        file_name = "/dev/stdin"
        basename="stdin"
    else:
        file_name = remainder[0]
        basename= filename= re.sub('\.[^.]*$','',file_name)

    signal = iq.read(file_name)

    cad = CutAndDownmix(center=center, input_sample_rate=sample_rate, symbols_per_second=symbols_per_second,
                            search_depth=search_depth, verbose=verbose, decimation=decimation)

    signal, freq = cad.cut_and_downmix(signal=signal, search_offset=search_offset, search_window=search_window, frequency_offset=frequency_offset)

    iq.write("%s-f%010d.cut" % (os.path.basename(basename), freq), signal)
    print "output=","%s-f%10d.cut" % (os.path.basename(basename), freq)
Пример #7
0
    for i in range(len(auto_correlated)):
        auto_correlated[i] = numpy.angle(signal[i] * numpy.conj(time_shifted_signal[i])) / 2. / 3.14 * Tu / 2
    #plt.plot(auto_correlated)
    #plt.show()

    fine_offset = numpy.average(auto_correlated)

    print "Fine frequency offset:", fine_offset
    return fine_offset


if __name__ == "__main__":
    import iq
    sample_rate = 2000000

    #Tu = int(2048 * (sample_rate/2048000.))
    Tu = sample_rate / 1000

    signal = iq.read(sys.argv[1])

    time_shifted_signal = signal[Tu:]

    auto_correlated = [0] * len(time_shifted_signal)
    for i in range(len(time_shifted_signal)):
        #auto_correlated[i] = numpy.angle(signal[i] * numpy.conj(time_shifted_signal[i]))/ 2 / 3.14 * 1000
        auto_correlated[i] = numpy.angle(signal[i] * numpy.conj(time_shifted_signal[i]))/ 2 / 3.14 * Tu / 2

    #print auto_correlated

    iq.write("/tmp/bar.cfile", auto_correlated)
Пример #8
0
    if verbose:
        print "raw filename:",rawfile
        print "base freq:",freq

    d = Demod(sample_rate=sample_rate, use_correlation=use_correlation, verbose=verbose, debug=debug)

    dataarray, data, access_ok, lead_out_ok, confidence, level, nsymbols = d.demod(signal)

    print "RAW: %s %07d %010d A:%s L:%s %3d%% %.3f %3d %s"%(rawfile,timestamp,freq,("no","OK")[access_ok],("no","OK")[lead_out_ok],confidence,level,(nsymbols-12),data)

    if 0: # Create r / phi file
        with open("%s.rphi" % (os.path.basename(basename)), 'wb') as out:
            signal = [item for sample
                in signal for item
                in [abs(sample), cmath.phase(sample)]]
            s = "<" + len(signal) * 'f'
            out.write(struct.Struct(s).pack(*signal))

    if debug: # The graphical debugging file
        iq.write("%s.peaks" % (os.path.basename(basename)), d.peaks)

    if 0: # The actual samples we used
        iq.write("%s.samples" % (os.path.basename(basename)), mynormalize(d.samples))

    if 0: # The data bitstream
        with open("%s.data" % (os.path.basename(basename)), 'wb') as out:
            for c in dataarray:
                out.write(chr(c))

    if sample_rate == None:
        print >> sys.stderr, "Sample rate missing!"
        exit(1)
    if center == None:
        print >> sys.stderr, "Need to specify center frequency!"
        exit(1)

    if len(remainder) == 0:
        file_name = "/dev/stdin"
        basename = "stdin"
    else:
        file_name = remainder[0]
        basename = filename = re.sub('\.[^.]*$', '', file_name)

    signal = iq.read(file_name)

    cad = CutAndDownmix(center=center,
                        sample_rate=sample_rate,
                        symbols_per_second=symbols_per_second,
                        preamble_length=preamble_length,
                        search_depth=search_depth,
                        verbose=verbose)

    signal, freq = cad.cut_and_downmix(signal=signal,
                                       search_offset=search_offset,
                                       search_window=search_window)

    iq.write("%s-f%10d.cut" % (os.path.basename(basename), freq), signal)
    print "output=", "%s-f%10d.cut" % (os.path.basename(basename), freq)
Пример #10
0
    #shift_signal = numpy.exp(complex(0,-1)*numpy.arange(len(signal))*2*numpy.pi*offset/float(sample_rate))
    #signal = signal * shift_signal

    #phase = -1.21851901212
    #signal = signal * cmath.rect(1,-phase)

    max_cor = 0
    best_loc = 0
    best_shift = 0
    #for offset_khz in range(0, 1):
    #for offset_khz in range(-10, 10):
    #for offset_khz in range(-8, -6):
    #    offset = offset_khz * 1000
        #print offset_khz
    for offset in range(offset-500, offset+500):
        shift_signal = numpy.exp(complex(0,-1)*numpy.arange(len(signal))*2*numpy.pi*offset/float(sample_rate))
        signal_shifted = signal * shift_signal

        iq.write("/tmp/bar.cfile", signal_shifted)
        location, cor, phase = estimate_prs(signal_shifted, prs)    
        print offset, cor, location, phase

        if cor > max_cor:
            #print "better"
            max_cor = cor
            best_loc = location
            best_shift = offset

    print max_cor, best_loc, best_shift
    print best_loc + 492
Пример #11
0
import iq
import sys
import numpy
import make_prs
import matplotlib.pyplot as plt
import scipy.signal

sample_rate = 2000000

signal = iq.read(sys.argv[1])

offset = -6000
shift_signal = numpy.exp(
    complex(0, -1) * numpy.arange(len(signal)) * 2 * numpy.pi * offset /
    float(sample_rate))
signal = signal * shift_signal

iq.write("/tmp/bar.cfile", signal)
Пример #12
0
    def cut_and_downmix(self,
                        signal,
                        search_offset=None,
                        direction=None,
                        frequency_offset=0,
                        phase_offset=0):
        if self._verbose:
            iq.write("/tmp/signal.cfile", signal)

        #t0 = time.time()
        shift_signal = numpy.exp(
            complex(0, -1) * numpy.arange(len(signal)) * 2 * numpy.pi *
            search_offset / float(self._input_sample_rate))
        #print "t_shift_signal:", time.time() - t0

        #t0 = time.time()
        signal = signal * shift_signal
        #print "t_shift1:", time.time() - t0

        #t0 = time.time()
        signal = scipy.signal.fftconvolve(signal,
                                          self._input_low_pass,
                                          mode='same')
        #print "t_filter:", time.time() - t0

        #t0 = time.time()
        signal_center = self._center + search_offset
        if self._verbose:
            iq.write("/tmp/signal-shifted-filtered.cfile", signal)

        signal = signal[::self._decimation]
        if self._verbose:
            iq.write("/tmp/signal-filtered-deci.cfile", signal)

        # Ring Alert and Pager Channels have a 64 symbol preamble
        if signal_center > 1626000000:
            preamble_length = 64
            direction = iridium.DOWNLINK
        else:
            preamble_length = 16

        # Take the FFT over the preamble + 10 symbols from the unique word (UW)
        fft_length = 2**int(
            math.log(self._output_samples_per_symbol * (preamble_length + 10),
                     2))
        if self._verbose:
            print 'fft_length', fft_length

        #signal_mag = [abs(x) for x in signal]
        #plt.plot(normalize(signal_mag))
        #print "t_misc:", time.time() - t0

        #t0 = time.time()
        begin = self._signal_start(signal[:int(self._search_depth *
                                               self._output_sample_rate)])
        signal = signal[begin:]

        if self._verbose:
            print 'begin', begin
            iq.write("/tmp/signal-filtered-deci-cut-start.cfile", signal)
            iq.write("/tmp/signal-filtered-deci-cut-start-x2.cfile", signal**2)

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

        #t0 = time.time()
        signal_preamble = signal[:fft_length]**2

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

        if self._verbose:
            iq.write("/tmp/preamble-x2.cfile", signal_preamble)

        #plt.plot([x.real for x in signal_preamble])
        #plt.plot([x.imag for x in signal_preamble])
        #plt.show()

        signal_preamble = signal_preamble * numpy.blackman(
            len(signal_preamble))
        # Increase size of FFT to inrease resolution
        fft_result, fft_freq = self._fft(signal_preamble,
                                         len(signal_preamble) * 16)
        fft_bin_size = fft_freq[101] - fft_freq[100]

        if self._verbose:
            print 'FFT bin size (Hz)', fft_bin_size * 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 'FFT peak bin:', max_index
            print 'FFT peak bin (Hz)', (fft_freq[max_index] *
                                        self._output_sample_rate) / 2

        #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

        a = math.floor(real_index)
        corrected_index = fft_freq[a] + (real_index - a) * fft_bin_size
        offset_freq = corrected_index * self._output_sample_rate / 2.

        if self._verbose:
            print 'FFT bin correction', correction
            print 'FFT interpolated peak:', max_index - correction
            print 'FFT interpolated peak (Hz):', offset_freq

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

        #t0 = time.time()
        # 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
        if self._verbose:
            iq.write("/tmp/signal-filtered-deci-cut-start-shift.cfile", signal)
        #print "t_shift2:", time.time() - t0

        #t0 = time.time()
        preamble_uw = signal[:(preamble_length + 16) *
                             self._output_samples_per_symbol]

        if direction is not None:
            offset, phase, _ = self._sync_search.estimate_sync_word_freq(
                preamble_uw, preamble_length, direction)
        else:
            offset_dl, phase_dl, confidence_dl = self._sync_search.estimate_sync_word_freq(
                preamble_uw, preamble_length, iridium.DOWNLINK)
            offset_ul, phase_ul, confidence_ul = self._sync_search.estimate_sync_word_freq(
                preamble_uw, preamble_length, iridium.UPLINK)

            if confidence_dl > confidence_ul:
                direction = iridium.DOWNLINK
                offset = offset_dl
                phase = phase_dl
            else:
                direction = iridium.UPLINK
                offset = offset_ul
                phase = phase_ul

        if offset == None:
            raise DownmixError("No valid freq offset for sync word found")

        offset = -offset

        phase += phase_offset
        offset += frequency_offset
        #print "t_css:", time.time() - t0

        #t0 = time.time()
        shift_signal = numpy.exp(
            complex(0, -1) * numpy.arange(len(signal)) * 2 * numpy.pi *
            offset / float(self._output_sample_rate))
        signal = signal * shift_signal
        offset_freq += offset

        if self._verbose:
            iq.write("/tmp/signal-filtered-deci-cut-start-shift-shift.cfile",
                     signal)
        #print "t_shift3:", time.time() - t0

        #t0 = time.time()
        #plt.plot([cmath.phase(x) for x in signal[:fft_length]])

        # 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, -phase)

        if self._verbose:
            iq.write(
                "/tmp/signal-filtered-deci-cut-start-shift-shift-rotate.cfile",
                signal)

        signal = scipy.signal.fftconvolve(signal, self._rrc, 'same')

        #print "t_rrc:", time.time() - t0
        #plt.plot([x.real for x in signal])
        #plt.plot([x.imag for x in signal])

        #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(signal_preamble)
        #plt.show()

        return (signal, signal_center + offset_freq, direction)
Пример #13
0
    def cut_and_downmix(self, signal, search_offset=None, direction=None, frequency_offset=0, phase_offset=0):
        if self._verbose:
            iq.write("/tmp/signal.cfile", signal)

        #t0 = time.time()
        shift_signal = numpy.exp(complex(0,-1)*numpy.arange(len(signal))*2*numpy.pi*search_offset/float(self._input_sample_rate))
        #print "t_shift_signal:", time.time() - t0

        #t0 = time.time()
        signal = signal * shift_signal
        #print "t_shift1:", time.time() - t0

        #t0 = time.time()
        signal = scipy.signal.fftconvolve(signal, self._input_low_pass, mode='same')
        #print "t_filter:", time.time() - t0

        #t0 = time.time()
        signal_center = self._center + search_offset
        if self._verbose:
            iq.write("/tmp/signal-shifted-filtered.cfile", signal)

        signal = signal[::self._decimation]
        if self._verbose:
            iq.write("/tmp/signal-filtered-deci.cfile", signal)

        # Ring Alert and Pager Channels have a 64 symbol preamble
        if signal_center > 1626000000:
            preamble_length = 64
            direction = iridium.DOWNLINK
        else:
            preamble_length = 16

        # Take the FFT over the preamble + 10 symbols from the unique word (UW)
        fft_length = 2 ** int(math.log(self._output_samples_per_symbol * (preamble_length + 10), 2))
        if self._verbose:
            print 'fft_length', fft_length

        #signal_mag = [abs(x) for x in signal]
        #plt.plot(normalize(signal_mag))
        #print "t_misc:", time.time() - t0

        #t0 = time.time()
        begin = self._signal_start(signal[:int(self._search_depth * self._output_sample_rate)])
        signal = signal[begin:]

        if self._verbose:
            print 'begin', begin
            iq.write("/tmp/signal-filtered-deci-cut-start.cfile", signal)
            iq.write("/tmp/signal-filtered-deci-cut-start-x2.cfile", signal ** 2)

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

        #t0 = time.time()
        signal_preamble = signal[:fft_length] ** 2

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

        if self._verbose:
            iq.write("/tmp/preamble-x2.cfile", signal_preamble)

        #plt.plot([x.real for x in signal_preamble])
        #plt.plot([x.imag for x in signal_preamble])
        #plt.show()

        signal_preamble = signal_preamble * numpy.blackman(len(signal_preamble))
        # Increase size of FFT to inrease resolution
        fft_result, fft_freq = self._fft(signal_preamble, len(signal_preamble) * 16)
        fft_bin_size = fft_freq[101] - fft_freq[100]

        if self._verbose:
            print 'FFT bin size (Hz)', fft_bin_size * 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 'FFT peak bin:', max_index
            print 'FFT peak bin (Hz)', (fft_freq[max_index] * self._output_sample_rate) / 2

        #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



        a = math.floor(real_index)
        corrected_index = fft_freq[a] + (real_index - a) * fft_bin_size
        offset_freq = corrected_index * self._output_sample_rate / 2.

        if self._verbose:
            print 'FFT bin correction', correction
            print 'FFT interpolated peak:', max_index - correction
            print 'FFT interpolated peak (Hz):', offset_freq

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

        #t0 = time.time()
        # 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
        if self._verbose:
            iq.write("/tmp/signal-filtered-deci-cut-start-shift.cfile", signal)
        #print "t_shift2:", time.time() - t0

        #t0 = time.time()
        preamble_uw = signal[:(preamble_length + 16) * self._output_samples_per_symbol]

        if direction is not None:
            offset, phase, _ = self._sync_search.estimate_sync_word_freq(preamble_uw, preamble_length, direction)
        else:
            offset_dl, phase_dl, confidence_dl = self._sync_search.estimate_sync_word_freq(preamble_uw, preamble_length, iridium.DOWNLINK)
            offset_ul, phase_ul, confidence_ul = self._sync_search.estimate_sync_word_freq(preamble_uw, preamble_length, iridium.UPLINK)

            if confidence_dl > confidence_ul:
                direction = iridium.DOWNLINK
                offset = offset_dl
                phase = phase_dl
            else:
                direction = iridium.UPLINK
                offset = offset_ul
                phase = phase_ul

        if offset == None:
            raise DownmixError("No valid freq offset for sync word found")

        offset = -offset

        phase += phase_offset
        offset += frequency_offset
        #print "t_css:", time.time() - t0

        #t0 = time.time()
        shift_signal = numpy.exp(complex(0,-1)*numpy.arange(len(signal))*2*numpy.pi*offset/float(self._output_sample_rate))
        signal = signal*shift_signal
        offset_freq += offset

        if self._verbose:
            iq.write("/tmp/signal-filtered-deci-cut-start-shift-shift.cfile", signal)
        #print "t_shift3:", time.time() - t0

        #t0 = time.time()
        #plt.plot([cmath.phase(x) for x in signal[:fft_length]])

        # 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,-phase)

        if self._verbose:
            iq.write("/tmp/signal-filtered-deci-cut-start-shift-shift-rotate.cfile", signal)

        signal = scipy.signal.fftconvolve(signal, self._rrc, 'same')

        #print "t_rrc:", time.time() - t0
        #plt.plot([x.real for x in signal])
        #plt.plot([x.imag for x in signal])

        #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(signal_preamble)
        #plt.show()

        return (signal, signal_center+offset_freq, direction)