Ejemplo n.º 1
0
 def filter_range(self, start: int, end: int, fir_filter: Filter):
     self.iq_array[start:end] = fir_filter.work(self.iq_array[start:end])
     self._qad[start:end] = signal_functions.afp_demod(
         self.iq_array[start:end], self.noise_threshold,
         self.modulation_type, self.modulation_order,
         self.costas_loop_bandwidth)
     self.__invalidate_after_edit()
Ejemplo n.º 2
0
    def test_plot(self):
        modulator = Modulator("gfsk")
        modulator.modulation_type = "GFSK"
        modulator.samples_per_symbol = 100
        modulator.sample_rate = 1e6
        modulator.parameters[1] = 20e3
        modulator.parameters[0] = 10e3
        modulator.carrier_freq_hz = 15e3
        modulator.carrier_phase_deg = 90

        modulated_samples = modulator.modulate([True, False, True, False, False], 77)
        data = copy.deepcopy(modulated_samples)
        modulated_samples = modulator.modulate([False, True, True, True, True, False, True], 100, start=len(data))
        data = np.concatenate((data, modulated_samples))

        plt.subplot(2, 1, 1)
        axes = plt.gca()
        axes.set_ylim([-2,2])
        plt.plot(data.real)
        plt.title("Modulated Wave")

        plt.subplot(2, 1, 2)
        qad = signal_functions.afp_demod(np.ascontiguousarray(data), 0, "FSK")
        plt.plot(qad)
        plt.title("Quad Demod")

        plt.show()
Ejemplo n.º 3
0
    def test_noisy_rect(self):
        data = Signal(get_path_for_data_file("fsk.complex")).iq_array.data
        rect = afp_demod(data, 0.008, "FSK", 2)[5:15000]

        center = detect_center(rect)
        self.assertGreaterEqual(center, -0.0587)
        self.assertLessEqual(center, 0.02)
Ejemplo n.º 4
0
    def test_ask_center_detection(self):
        data = Signal(get_path_for_data_file("ask.complex")).iq_array.data
        rect = afp_demod(data, 0.01111, "ASK", 2)

        center = detect_center(rect)
        self.assertGreaterEqual(center, 0)
        self.assertLessEqual(center, 0.06)
Ejemplo n.º 5
0
 def test_fsk_15db_center_detection(self):
     data = Signal(get_path_for_data_file("FSK15.complex"),
                   "").iq_array.data
     rect = afp_demod(data, 0, "FSK", 2)
     center = detect_center(rect)
     self.assertGreaterEqual(center, -0.1979)
     self.assertLessEqual(center, 0.1131)
Ejemplo n.º 6
0
    def test_plot(self):
        modulator = Modulator("gfsk")
        modulator.modulation_type_str = "GFSK"
        modulator.samples_per_bit = 100
        modulator.sample_rate = 1e6
        modulator.param_for_one = 20e3
        modulator.param_for_zero = 10e3
        modulator.carrier_freq_hz = 15e3
        modulator.carrier_phase_deg = 90

        modulated_samples = modulator.modulate([True, False, True, False, False], 77)
        data = copy.deepcopy(modulated_samples)
        modulated_samples = modulator.modulate([False, True, True, True, True, False, True], 100, start=len(data))
        data = np.concatenate((data, modulated_samples))

        plt.subplot(2, 1, 1)
        axes = plt.gca()
        axes.set_ylim([-2,2])
        plt.plot(data.real)
        plt.title("Modulated Wave")

        plt.subplot(2, 1, 2)
        qad = signal_functions.afp_demod(np.ascontiguousarray(data), 0, 1)
        plt.plot(qad)
        plt.title("Quad Demod")

        plt.show()
Ejemplo n.º 7
0
    def test_ask_center_detection(self):
        data = np.fromfile(get_path_for_data_file("ask.complex"),
                           dtype=np.complex64)
        rect = afp_demod(data, 0.01111, 0)

        center = detect_center(rect)
        self.assertGreaterEqual(center, 0)
        self.assertLessEqual(center, 0.06)
Ejemplo n.º 8
0
    def test_noisy_rect(self):
        data = np.fromfile(get_path_for_data_file("fsk.complex"),
                           dtype=np.complex64)
        rect = afp_demod(data, 0.008, 1)[5:15000]

        center = detect_center(rect)
        self.assertGreaterEqual(center, -0.0587)
        self.assertLessEqual(center, 0.02)
Ejemplo n.º 9
0
    def test_fsk_live_capture(self):
        data = Signal(get_path_for_data_file("fsk_live.coco"), "").data

        n = 10
        moving_average_filter = Filter([1 / n for _ in range(n)],
                                       filter_type=FilterType.moving_average)
        filtered_data = moving_average_filter.apply_fir_filter(data)

        rect = afp_demod(filtered_data, 0.0175, 1)
        center = detect_center(rect)
        self.assertGreaterEqual(center, -0.0148, msg="Filtered")
        self.assertLessEqual(center, 0.01, msg="Filtered")

        rect = afp_demod(data, 0.0175, 1)
        center = detect_center(rect)
        self.assertGreaterEqual(center, -0.02, msg="Original")
        self.assertLessEqual(center, 0.01, msg="Original")
Ejemplo n.º 10
0
    def test_enocean_center_detection(self):
        data = Signal(get_path_for_data_file("enocean.complex")).iq_array.data
        rect = afp_demod(data, 0.05, "ASK", 2)
        messages = [rect[2107:5432], rect[20428:23758], rect[44216:47546]]

        for i, msg in enumerate(messages):
            center = detect_center(msg)
            self.assertGreaterEqual(center, 0.04, msg=str(i))
            self.assertLessEqual(center, 0.072, msg=str(i))
Ejemplo n.º 11
0
 def quad_demod(self):
     if self.noise_threshold < self.max_magnitude:
         return signal_functions.afp_demod(self.iq_array.data,
                                           self.noise_threshold,
                                           self.modulation_type,
                                           self.modulation_order,
                                           self.costas_loop_bandwidth)
     else:
         return np.zeros(2, dtype=np.float32)
Ejemplo n.º 12
0
    def test_noised_homematic_center_detection(self):
        data = Signal(get_path_for_data_file("noised_homematic.complex"),
                      "").iq_array.data
        rect = afp_demod(data, 0.0, "FSK", 2)

        center = detect_center(rect)

        self.assertGreater(center, -0.0148)
        self.assertLess(center, 0.0024)
Ejemplo n.º 13
0
    def test_enocean_center_detection(self):
        data = np.fromfile(get_path_for_data_file("enocean.complex"),
                           dtype=np.complex64)
        rect = afp_demod(data, 0.05, 0)
        messages = [rect[2107:5432], rect[20428:23758], rect[44216:47546]]

        for i, msg in enumerate(messages):
            center = detect_center(msg)
            self.assertGreaterEqual(center, 0.04, msg=str(i))
            self.assertLessEqual(center, 0.072, msg=str(i))
Ejemplo n.º 14
0
    def test_fsk_live_capture(self):
        data = Signal(get_path_for_data_file("fsk_live.coco"),
                      "").iq_array.data

        n = 10
        moving_average_filter = Filter([1 / n for _ in range(n)],
                                       filter_type=FilterType.moving_average)
        filtered_data = moving_average_filter.apply_fir_filter(
            data.flatten()).view(np.float32)
        filtered_data = filtered_data.reshape((len(filtered_data) // 2, 2))

        rect = afp_demod(filtered_data, 0.0175, "FSK", 2)
        center = detect_center(rect)
        self.assertGreaterEqual(center, -0.0148, msg="Filtered")
        self.assertLessEqual(center, 0.01, msg="Filtered")

        rect = afp_demod(data, 0.0175, "FSK", 2)
        center = detect_center(rect)
        self.assertGreaterEqual(center, -0.02, msg="Original")
        self.assertLessEqual(center, 0.01, msg="Original")
Ejemplo n.º 15
0
    def test_ask_50_center_detection(self):
        message_indices = [(0, 8000), (18000, 26000), (36000, 44000),
                           (54000, 62000), (72000, 80000)]

        data = Signal(get_path_for_data_file("ask50.complex")).iq_array.data
        rect = afp_demod(data, 0.0509, "ASK", 2)

        for start, end in message_indices:
            center = detect_center(rect[start:end])
            self.assertGreaterEqual(center,
                                    0.4,
                                    msg="{}/{}".format(start, end))
            self.assertLessEqual(center, 0.65, msg="{}/{}".format(start, end))
Ejemplo n.º 16
0
    def test_homematic_center_detection(self):
        data = Signal(get_path_for_data_file("homematic.coco"), "").data
        rect = afp_demod(data, 0.0012, 1)

        msg1 = rect[17719:37861]
        msg2 = rect[70412:99385]

        center1 = detect_center(msg1)
        self.assertGreaterEqual(center1, -0.1285)
        self.assertLessEqual(center1, -0.0413)

        center2 = detect_center(msg2)
        self.assertGreaterEqual(center2, -0.1377)
        self.assertLessEqual(center2, -0.0367)
Ejemplo n.º 17
0
    def test_ask_50_center_detection(self):
        message_indices = [(0, 8000), (18000, 26000), (36000, 44000),
                           (54000, 62000), (72000, 80000)]

        data = np.fromfile(get_path_for_data_file("ask50.complex"),
                           dtype=np.complex64)
        rect = afp_demod(data, 0.0509, 0)

        for start, end in message_indices:
            center = detect_center(rect[start:end])
            self.assertGreaterEqual(center,
                                    0.5326,
                                    msg="{}/{}".format(start, end))
            self.assertLessEqual(center,
                                 0.9482,
                                 msg="{}/{}".format(start, end))
Ejemplo n.º 18
0
Archivo: Signal.py Proyecto: jopohl/urh
 def filter_range(self, start: int, end: int, fir_filter: Filter):
     self._fulldata[start:end] = fir_filter.work(self._fulldata[start:end])
     self._qad[start:end] = signal_functions.afp_demod(self.data[start:end],
                                                       self.noise_threshold, self.modulation_type)
     self.__invalidate_after_edit()
Ejemplo n.º 19
0
 def test_fsk_10db_center_detection(self):
     data = Signal(get_path_for_data_file("FSK10.complex"), "").data
     rect = afp_demod(data, 0, 1)
     center = detect_center(rect)
     self.assertGreaterEqual(center, -0.1413)
     self.assertLessEqual(center, 0.05)
Ejemplo n.º 20
0
 def quad_demod(self):
     return signal_functions.afp_demod(self.iq_array.data,
                                       self.noise_threshold,
                                       self.modulation_type)
Ejemplo n.º 21
0
Archivo: Signal.py Proyecto: jopohl/urh
 def quad_demod(self):
     return signal_functions.afp_demod(self.data, self.noise_threshold, self.modulation_type)
Ejemplo n.º 22
0
 def quad_demod(self):
     return signal_functions.afp_demod(self.iq_array.data,
                                       self.noise_threshold,
                                       self.modulation_type,
                                       self.modulation_order,
                                       self.costas_loop_bandwidth)
Ejemplo n.º 23
0
 def filter_range(self, start: int, end: int, fir_filter: Filter):
     self._fulldata[start:end] = fir_filter.work(self._fulldata[start:end])
     self._qad[start:end] = signal_functions.afp_demod(
         self.data[start:end], self.noise_threshold, self.modulation_type)
     self.__invalidate_after_edit()
Ejemplo n.º 24
0
def estimate(iq_array: IQArray,
             noise: float = None,
             modulation: str = None) -> dict:
    if isinstance(iq_array, np.ndarray):
        iq_array = IQArray(iq_array)

    magnitudes = iq_array.magnitudes
    # find noise threshold
    noise = detect_noise_level(magnitudes) if noise is None else noise

    # segment messages
    message_indices = segment_messages_from_magnitudes(magnitudes,
                                                       noise_threshold=noise)

    # detect modulation
    modulation = detect_modulation_for_messages(
        iq_array, message_indices) if modulation is None else modulation
    if modulation is None:
        return None

    if modulation == "OOK":
        message_indices = merge_message_segments_for_ook(message_indices)

    if modulation == "OOK" or modulation == "ASK":
        data = signal_functions.afp_demod(iq_array.data, noise, 0)
    elif modulation == "FSK":
        data = signal_functions.afp_demod(iq_array.data, noise, 1)
    elif modulation == "PSK":
        data = signal_functions.afp_demod(iq_array.data, noise, 2)
    else:
        raise ValueError("Unsupported Modulation")

    centers = []
    bit_lengths = []
    tolerances = []
    for start, end in message_indices:
        msg_rect_data = data[start:end]

        center = detect_center(msg_rect_data)
        if center is None:
            continue

        plateau_lengths = c_auto_interpretation.get_plateau_lengths(
            msg_rect_data, center, percentage=25)
        tolerance = estimate_tolerance_from_plateau_lengths(plateau_lengths)
        if tolerance is None:
            tolerance = 0
        else:
            tolerances.append(tolerance)

        merged_lengths = merge_plateau_lengths(plateau_lengths,
                                               tolerance=tolerance)
        if len(merged_lengths) < 2:
            continue

        bit_length = get_bit_length_from_plateau_lengths(merged_lengths)

        min_bit_length = tolerance + 1

        if bit_length > min_bit_length:
            # only add to score if found bit length surpasses minimum bit length
            centers.append(center)
            bit_lengths.append(bit_length)

    # Since we cannot have different centers per message (yet) we need to combine them to return a common center
    if modulation == "OOK" or modulation == "ASK":
        # for ask modulations the center tends to be the minimum of all found centers
        center = min_without_outliers(np.array(centers), z=2)
        if center is None:
            # did not find any centers at all so we cannot return a valid estimation
            return None
    elif len(centers) > 0:
        # for other modulations it is a better strategy to take the mean of found centers
        center = np.mean(centers)
    else:
        # did not find any centers at all so we cannot return a valid estimation
        return None

    bit_length = get_most_frequent_value(bit_lengths)
    if bit_length is None:
        return None

    try:
        tolerance = np.percentile(tolerances, 50)
    except IndexError:
        # no tolerances found, default to 5% of bit length
        tolerance = max(1, int(0.05 * bit_length))

    result = {
        "modulation_type": "ASK" if modulation == "OOK" else modulation,
        "bit_length": bit_length,
        "center": center,
        "tolerance": int(tolerance),
        "noise": noise
    }

    return result
Ejemplo n.º 25
0
def estimate(signal: np.ndarray, noise: float = None, modulation: str = None) -> dict:
    magnitudes = np.abs(signal)
    # find noise threshold
    noise = detect_noise_level(magnitudes) if noise is None else noise

    # segment messages
    message_indices = segment_messages_from_magnitudes(magnitudes, noise_threshold=noise)

    # detect modulation
    modulation = detect_modulation_for_messages(signal, message_indices) if modulation is None else modulation
    if modulation is None:
        return None

    if modulation == "OOK":
        message_indices = merge_message_segments_for_ook(message_indices)

    if modulation == "OOK" or modulation == "ASK":
        data = signal_functions.afp_demod(signal, noise, 0)
    elif modulation == "FSK":
        data = signal_functions.afp_demod(signal, noise, 1)
    elif modulation == "PSK":
        data = signal_functions.afp_demod(signal, noise, 2)
    else:
        raise ValueError("Unsupported Modulation")

    centers = []
    bit_lengths = []
    tolerances = []
    for start, end in message_indices:
        msg_rect_data = data[start:end]

        center = detect_center(msg_rect_data)
        if center is None:
            continue

        plateau_lengths = c_auto_interpretation.get_plateau_lengths(msg_rect_data, center, percentage=25)
        tolerance = estimate_tolerance_from_plateau_lengths(plateau_lengths)
        if tolerance is None:
            tolerance = 0
        else:
            tolerances.append(tolerance)

        merged_lengths = merge_plateau_lengths(plateau_lengths, tolerance=tolerance)
        if len(merged_lengths) < 2:
            continue

        bit_length = get_bit_length_from_plateau_lengths(merged_lengths)

        min_bit_length = tolerance + 1

        if bit_length > min_bit_length:
            # only add to score if found bit length surpasses minimum bit length
            centers.append(center)
            bit_lengths.append(bit_length)

    # Since we cannot have different centers per message (yet) we need to combine them to return a common center
    if modulation == "OOK" or modulation == "ASK":
        # for ask modulations the center tends to be the minimum of all found centers
        center = min_without_outliers(np.array(centers), z=2)
        if center is None:
            # did not find any centers at all so we cannot return a valid estimation
            return None
    elif len(centers) > 0:
        # for other modulations it is a better strategy to take the mean of found centers
        center = np.mean(centers)
    else:
        # did not find any centers at all so we cannot return a valid estimation
        return None

    bit_length = get_most_frequent_value(bit_lengths)
    if bit_length is None:
        return None

    try:
        tolerance = np.percentile(tolerances, 50)
    except IndexError:
        # no tolerances found, default to 5% of bit length
        tolerance = max(1, int(0.05 * bit_length))

    result = {
        "modulation_type": "ASK" if modulation == "OOK" else modulation,
        "bit_length": bit_length,
        "center": center,
        "tolerance": int(tolerance),
        "noise": noise
    }

    return result