From d00bb6d29ceae9d2ee958b57549af335e977edc6 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Thu, 18 Nov 2021 19:07:03 +0100 Subject: Partially implement xor correlator (untested) --- src/gr-fadingui/build.sh | 8 ---- src/gr-fadingui/install.sh | 8 ++++ src/gr-fadingui/python/datasource.py | 3 +- src/gr-fadingui/python/xor_frame_sync.py | 70 ++++++++++++++++++++------------ tests/fadingui/QAM/qam_nogui.grc | 10 ++--- tests/fadingui/QAM/qam_nogui.py | 4 +- 6 files changed, 61 insertions(+), 42 deletions(-) delete mode 100755 src/gr-fadingui/build.sh create mode 100755 src/gr-fadingui/install.sh diff --git a/src/gr-fadingui/build.sh b/src/gr-fadingui/build.sh deleted file mode 100755 index 29697af..0000000 --- a/src/gr-fadingui/build.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -mkdir -p build -cmake -DGR_PYTHON_DIR=/usr/lib/python3/dist-packages/ -GNinja -Bbuild -ninja -C build - -# install to system -sudo ninja -C build install diff --git a/src/gr-fadingui/install.sh b/src/gr-fadingui/install.sh new file mode 100755 index 0000000..29697af --- /dev/null +++ b/src/gr-fadingui/install.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +mkdir -p build +cmake -DGR_PYTHON_DIR=/usr/lib/python3/dist-packages/ -GNinja -Bbuild +ninja -C build + +# install to system +sudo ninja -C build install diff --git a/src/gr-fadingui/python/datasource.py b/src/gr-fadingui/python/datasource.py index ab2f441..c7d68f1 100644 --- a/src/gr-fadingui/python/datasource.py +++ b/src/gr-fadingui/python/datasource.py @@ -8,6 +8,7 @@ import io import numpy as np from gnuradio import gr + class datasource(gr.sync_block): """ Loads data from a file choosen in the graphical user interface, splits into @@ -51,7 +52,7 @@ class datasource(gr.sync_block): def make_header(self, data_size): # TODO: check that data_size is not too big - pilot = 0x1248 + pilot = 0xbeef # TODO: implement hamming code for header header = f"p{pilot:04x}s{data_size:04x}d".encode("ascii") diff --git a/src/gr-fadingui/python/xor_frame_sync.py b/src/gr-fadingui/python/xor_frame_sync.py index 735a031..af7aa85 100644 --- a/src/gr-fadingui/python/xor_frame_sync.py +++ b/src/gr-fadingui/python/xor_frame_sync.py @@ -12,36 +12,48 @@ from gnuradio import gr class xor_frame_sync(gr.sync_block): """ - docstring for block xor_frame_sync + Performs a frame synchronization by XOR matching a preamble bit sequence """ def __init__(self, sync_pattern, buffer_size): + # TODO: buffer size should be in packets gr.sync_block.__init__(self, name="xor_frame_sync", in_sig=[np.byte], out_sig=[np.byte]) # binary pattern to match - self.pattern = np.array(sync_pattern, dtype=np.dtype("uint8")) - self.nbits = len(sync_pattern) + self.pattern = np.unpackbits(np.array(sync_pattern, dtype=np.uint8))[::-1] + self.nbytes = len(sync_pattern) + self.nbits = len(self.pattern) - # buffer to delay the data - self.delay_fifo = RingBuffer(buffer_size, dtype=np.byte) + assert(self.nbits % 8 == 0) - # buffers to store cross correlation data - self.xcorr = RingBuffer(buffer_size, dtype=np.dtype("uint8")) + # packed buffer to delay the data + self.delaybuf = RingBuffer(buffer_size, dtype=np.uint8) + self.delay = 0 + + # unpacked buffer to compute correlation values, initially filled with zeros + self.corrbuf = RingBuffer(self.nbits) + self.corrbuf.extend(np.zeros(self.nbits)) + + # buffer to store correlation values + self.xcorrs = RingBuffer(buffer_size) # synchronization state self.synchronized = False - self.delay = 0 - def xcorrelation(self): + def xcorrelation(self, v): """ - Compute the binary correlation between the stream and the stored - pattern. Binary correlation between two bit vectors is just size of the + Compute the binary correlations between the stored pattern and + correlation buffer, while shifting v into the buffer. + + Binary correlation between two bit vectors is just size of the vector(s) minus the number of bits that differ. """ - unpacked = np.unpackbits(self.delay_fifo[0]) - return self.nbits - sum(np.logical_xor(unpacked, self.pattern)) + v_arr = np.array(v, dtype=np.uint8) + for b in np.unpackbits(v_arr): + self.corrbuf.appendleft(b) + yield self.nbits - np.sum(np.logical_xor(self.corrbuf, self.pattern)) def work(self, input_items, output_items): """ @@ -51,29 +63,37 @@ class xor_frame_sync(gr.sync_block): pattern appears every k bits, where k is the size of the packet. - If the buffer is not synchronized, compute a binary cross - correlation to find how by much the stream should be delayed. + correlation to find how much the stream should be delayed. + + Notes: + + - Even though the block input is of type np.byte, inp is an array + of 255 bytes, probably for performance reasons. + TODO: block processing """ inp = input_items[0] out = output_items[0] - # Add data to delay buffer - self.delay_fifo.appendleft(inp) - - # TODO: check for synchronization, else compute - - # Compute correlation if not self.synchronized: - self.xcorr.append(self.xcorrelation()) + for v in inp: + # compute the cross correlation + xcs = self.xcorrelation(v) - peak = np.argmax(self.xcorr) - if self.xcorr[peak] != self.nbits: - print(f"Warning! XOR correlation is not perfect (peak value = {self.xcorr[peak]})") + # add cross correlations to buffer and save value + self.xcorrs.extend(list(xcs)) + self.delaybuf.appendleft(v) + peak = np.argmax(self.xcorrs) self.delay = peak self.synchronized = True + if self.xcorrs[peak] != self.nbits: + self.synchronized = False + print(f"Warning! XOR correlation is not perfect (peak value = {self.xcorrs[peak]})") + + # return data with delay - out[:] = self.delay_fifo[self.delay] + out[:] = self.delaybuf[self.delay] return len(output_items[0]) diff --git a/tests/fadingui/QAM/qam_nogui.grc b/tests/fadingui/QAM/qam_nogui.grc index e9028b6..83c8059 100644 --- a/tests/fadingui/QAM/qam_nogui.grc +++ b/tests/fadingui/QAM/qam_nogui.grc @@ -488,23 +488,23 @@ blocks: bus_structure: null coordinate: [2096, 180.0] rotation: 0 - state: true + state: disabled - name: fadingui_xor_frame_sync_0 id: fadingui_xor_frame_sync parameters: affinity: '' alias: '' - buffer_size: '128' + buffer_size: '2048' comment: '' maxoutbuf: '0' minoutbuf: '0' - pattern: '[]' - pattern_len: '10' + pattern: '[0xbe, 0xef]' + pattern_len: '16' states: bus_sink: false bus_source: false bus_structure: null - coordinate: [2304, 436.0] + coordinate: [2312, 436.0] rotation: 0 state: true diff --git a/tests/fadingui/QAM/qam_nogui.py b/tests/fadingui/QAM/qam_nogui.py index 56fc49b..1da693e 100755 --- a/tests/fadingui/QAM/qam_nogui.py +++ b/tests/fadingui/QAM/qam_nogui.py @@ -52,8 +52,7 @@ class qam_nogui(gr.top_block): ################################################## # Blocks ################################################## - self.fadingui_xor_frame_sync_0 = fadingui.xor_frame_sync(sync_pattern=[], buffer_size=128) - self.fadingui_dearpygui_sink_0 = fadingui.dearpygui_sink(sock_addr='udp://localhost:31415', ui_element_id=0) + self.fadingui_xor_frame_sync_0 = fadingui.xor_frame_sync(sync_pattern=[0xbe, 0xef], buffer_size=2048) self.fadingui_datasource_0 = fadingui.datasource(vec_len=2037, header_len=11, sock_addr='udp://', file_list=["./lena512color.tiff"]) self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, nfilts/2, 1.5, 1) self.digital_map_bb_0 = digital.map_bb([0, 1, 3, 2]) @@ -92,7 +91,6 @@ class qam_nogui(gr.top_block): self.connect((self.digital_constellation_decoder_cb_0, 0), (self.digital_diff_decoder_bb_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.blocks_throttle_0, 0)) self.connect((self.digital_costas_loop_cc_0, 0), (self.digital_constellation_decoder_cb_0, 0)) - self.connect((self.digital_costas_loop_cc_0, 0), (self.fadingui_dearpygui_sink_0, 0)) self.connect((self.digital_diff_decoder_bb_0, 0), (self.digital_map_bb_0, 0)) self.connect((self.digital_map_bb_0, 0), (self.fadingui_xor_frame_sync_0, 0)) self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_cma_equalizer_cc_0, 0)) -- cgit v1.2.1