Beispiel #1
0
 def calculate_error(self):
     errors = 0
     N1, N2 = len(self.sent_data), len(self.received_data)
     if N1 != N2:
         log.warning(f'Did not receive correct number of bits, expected {N1}, received {N2}')
     for b1, b2 in zip(self.sent_data, self.received_data):
         if b1 != b2:
             errors += 1
     log.special(f'No of errors: {errors}')
     log.special(f'Percent error: {100*errors/max(N1, N2):3}%')
Beispiel #2
0
 def listen_for_text(self, threshold=0.5):
     self.record()
     output_queue = named_deque()
     self.listen(output_queue, threshold)
     while True:
         try:
             received_bits = np.concatenate(list(output_queue))
             output_queue.clear()
             received_bytes = np.packbits(received_bits)
             text = bytes(received_bytes)
             log.special(text)
         except:
             time.sleep(5)
Beispiel #3
0
    def peak_finder(self,
                    input_queue: deque,
                    threshold,
                    search_width: int,
                    output_queue=None):
        N = search_width
        data_old = np.zeros(N)
        # buffer = named_deque(maxlen=10)
        while self.recording_flag:
            try:
                # Get next chunk from queue
                data_new, block_num = input_queue.popleft()
            except IndexError:
                time.sleep(0.25)
                continue

            # Extend with previous data for convolution
            data = np.concatenate((data_old, data_new))
            data_old = data[-N:]

            # Find the index of the peak
            n = np.argmax(data)

            # Make sure that the peak is in the valid convolution region
            if n < (len(data) - N) and data[n] > threshold:
                log.info('Sync pulse detected')
            else:
                # If peak in in right hand invalid region, get next chunk of data
                continue

            # Get block number and sample index of star of signal (at n-search_width)
            for i in range(10):
                if n - search_width + self.audio_block_size * i >= 0:
                    transmission_start = (block_num - i, n - search_width +
                                          self.audio_block_size * i)
                    log.special(f'Peak detected at {transmission_start}')
                    break
            else:
                log.error('Failed to send peak location')
                continue

            if type(output_queue) == named_deque:
                output_queue.append(transmission_start)
Beispiel #4
0
    def test_transmission(self, bit_count=100, threshold=0.5):
        random.seed(100)
        test_packet = Packet([(random.getrandbits(1)) for i in range(bit_count)])
        log.info(f'Sending test transmission - length={len(test_packet.unpack())}')
        self.sent_data = test_packet.unpack()

        self.r.record()
        data_bits_output_queue = named_deque()
        self.r.listen(data_bits_output_queue, threshold=threshold)

        # Transmit and wait till demodulated
        self.t.transmit(test_packet)
        # Todo change this to be none blocking so plots etc. can be shown
        while not self.r.demodulator.demodulated_flag:
            time.sleep(0.1)
        self.r.demodulator.demodulated_flag = False
        self.received_data = np.concatenate(list(data_bits_output_queue))

        received_bytes = np.packbits(self.received_data)
        text = bytes(received_bytes)
        log.special(f'Received data in bytes form {text}')
Beispiel #5
0
 def text_to_bits(self, text: str):
     send_bytes = list(text.encode())
     log.special(f'send_bytes {send_bytes}')
     return np.unpackbits(np.array(send_bytes, dtype='uint8'))
Beispiel #6
0
    def demodulate(self, transmission_start_index, audio_data_queue,
                   output_queue):
        log.special(transmission_start_index)
        data, start_block_index = self.find_transmission_start(
            transmission_start_index, audio_data_queue)

        # Phy level data of fixed length:
        # Get phy level data i.e. symbol_width, symbol count

        audio_block_size = self.defaults['audio_block_size']
        initial_pulse_width = self.defaults['ampam']['initial_pulse_width']
        threshold_data_bits = self.defaults['ampam']['threshold_data_bits']
        pulse_width_data_bits = self.defaults['ampam']['pulse_width_data_bits']
        pulse_count_data_bits = self.defaults['ampam']['pulse_count_data_bits']
        initial_pulse_count = pulse_width_data_bits + pulse_count_data_bits + threshold_data_bits

        # TODO make into a function
        while len(data) < initial_pulse_count * initial_pulse_width:
            try:
                data_new, block_num = audio_data_queue.popleft()
                data = np.append(data, data_new)
            except IndexError:
                time.sleep(0.5)
        data, phy_bits, = self.ampam_demod(
            data,
            initial_pulse_width,
            initial_pulse_count,
            thresholding_bits=threshold_data_bits,
        )

        # Calculate no of audio blocks required
        # TODO manage this better
        pulse_width_bytes = np.packbits(
            phy_bits[threshold_data_bits:threshold_data_bits +
                     pulse_width_data_bits])
        pulse_count_bytes = np.packbits(
            phy_bits[threshold_data_bits +
                     pulse_width_data_bits:threshold_data_bits +
                     pulse_width_data_bits + pulse_count_data_bits])

        pulse_width = pulse_width_bytes[0] * 2**8 + pulse_width_bytes[1]
        pulse_count = pulse_count_bytes[0] * 2**8 + pulse_count_bytes[1]
        log.debug(
            f'Receiving pam with pulse_count {pulse_count} pulse_width {pulse_width}'
        )

        total_transmission_length = initial_pulse_count * initial_pulse_width + pulse_count * pulse_width
        end_block_index = start_block_index + math.floor(
            (transmission_start_index[1] + total_transmission_length) /
            audio_block_size)
        end_block_n = (total_transmission_length +
                       transmission_start_index[1]) % audio_block_size
        log.debug(
            f'Calculated end block index = {end_block_index}, current block_num {block_num}'
        )
        log.debug(
            f'Calculated end block n = {end_block_n}, total trans length {total_transmission_length}, original n {transmission_start_index[1]}'
        )

        if end_block_index == block_num:
            log.warning('egg')
            data = data[:pulse_count * pulse_width + 1]
        else:
            while block_num < end_block_index:
                try:
                    data_new, block_num = audio_data_queue.popleft()
                    if block_num == end_block_index:
                        data = np.append(data, data_new[:end_block_n])
                        break
                    else:
                        data = np.append(data, data_new)
                except IndexError:
                    if len(data) > 1000 * pulse_width:
                        # TODO bayesian updating of mean, incorporating new data, and old data prior to give posterior point estimate for mean
                        data, bits = self.ampam_demod(data, pulse_width)
                        output_queue.append(bits)
                    else:
                        time.sleep(0.1)
        data, bits = self.ampam_demod(data, pulse_width)
        output_queue.append(bits)

        self.demodulated_flag = True
        log.info('Demodulated')