diff options
author | Nao Pross <np@0hm.ch> | 2021-11-22 19:59:14 +0100 |
---|---|---|
committer | Nao Pross <np@0hm.ch> | 2021-11-22 19:59:14 +0100 |
commit | ec407f3bf29eca3271b428859b258b43222265c9 (patch) | |
tree | a62e18c762a256b2771029c5732d92cfdcda32f7 /src/gr-fadingui/python/xor_frame_sync.py | |
parent | Make install.sh run QA (diff) | |
download | Fading-ec407f3bf29eca3271b428859b258b43222265c9.tar.gz Fading-ec407f3bf29eca3271b428859b258b43222265c9.zip |
Implement frame synchronization
There is an issue somewhere between the mod and demod, since frame
synchronization works on a direct path.
Diffstat (limited to '')
-rw-r--r-- | src/gr-fadingui/python/xor_frame_sync.py | 101 |
1 files changed, 68 insertions, 33 deletions
diff --git a/src/gr-fadingui/python/xor_frame_sync.py b/src/gr-fadingui/python/xor_frame_sync.py index 51af35a..e52b493 100644 --- a/src/gr-fadingui/python/xor_frame_sync.py +++ b/src/gr-fadingui/python/xor_frame_sync.py @@ -25,23 +25,24 @@ class xor_frame_sync(gr.sync_block): out_sig=[np.byte]) # binary pattern to match - self.pattern = np.unpackbits(np.array(sync_pattern, dtype=np.uint8))[::-1] - self.nbytes = len(sync_pattern) - self.nbits = len(self.pattern) + self.pattern = sync_pattern + self.nbytes = len(self.pattern) - log.debug(f"Loaded pattern {self.pattern} length={self.nbits}") + self.pattern_bits = np.unpackbits(np.array(self.pattern, dtype=np.uint8))[::-1] + self.nbits = len(self.pattern_bits) + + log.debug(f"Loaded pattern {self.pattern_bits} length={self.nbits}") assert(self.nbits % 8 == 0) # 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)) + log.debug(f"Created delay ring buffer of size {self.delaybuf.maxlen}") - # buffer to store correlation values - self.xcorrs = RingBuffer(buffer_size) + # unpacked buffer to compute correlation values, initially filled with zeros + self.corrbuf = RingBuffer(self.nbits, dtype=np.uint8) + self.corrbuf.extend(np.zeros(self.corrbuf.maxlen)) # synchronization state self.synchronized = False @@ -53,11 +54,21 @@ class xor_frame_sync(gr.sync_block): Binary correlation between two bit vectors is just size of the vector(s) minus the number of bits that differ. + + @return: Number of bits of v that were shifted into the buffer + when the correlation matched. If no match is found + the return value is None. """ - v_arr = np.array(v, dtype=np.uint8) - for b in np.unpackbits(v_arr): + # this could be much faster with shifts, bitwise or and xor + # but this should do alright for the moment + v_bits = np.unpackbits(np.array(v, dtype=np.uint8)) + for bitnr, b in enumerate(v_bits): self.corrbuf.appendleft(b) - yield self.nbits - np.sum(np.logical_xor(self.corrbuf, self.pattern)) + if (np.bitwise_xor(self.corrbuf, self.pattern_bits) == 0).all(): + return bitnr + + # no cross correlation found + return None def work(self, input_items, output_items): """ @@ -68,35 +79,59 @@ class xor_frame_sync(gr.sync_block): - If the buffer is not synchronized, compute a binary cross 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] - if not self.synchronized: - for v in inp: - # compute the cross correlation - xcs = self.xcorrelation(v) + inp_len = len(inp) - # add cross correlations to buffer and save value - self.xcorrs.extend(list(xcs)) - self.delaybuf.appendleft(v) + if not self.synchronized: + if inp_len > self.delaybuf.maxlen: + log.error("Input is bigger than delay buffer") - peak = np.argmax(self.xcorrs) - if self.xcorrs[peak] == self.nbits: - self.delay = peak - self.synchronized = True - log.debug(f"Synchronized with delay={peak}") + # FIXME: Makes the QA hang for some reason + # raise NotImplemented - else: - self.synchronized = False - log.warning(f"Did not find a peak (max={self.xcorrs[peak]}, should be {self.nbits})") + for bytenr, value in enumerate(inp): + # save value in the buffer + self.delaybuf.appendleft(value) + # compute the cross correlation + bitnr = self.xcorrelation(value) + if bitnr is not None: + # correlation was found + delay_bits = 8 * bytenr + bitnr + + # FIXME: add bit delay + self.delay = bytenr + self.synchronized = True + log.debug(f"Synchronized with delay={self.delay} delay_bits={delay_bits}") + + # Not aligned to bytes + if bitnr != 7: + log.error("Not implemented: byte unaligned delay") + self.synchronized = False + self.delay = 0 + + # FIXME: Makes the QA hang for some reason + # raise NotImplemented + + # bigger than buffer + if bytenr > self.delaybuf.maxlen: + log.error("Too too long to synchronize, ran out of buffer memory") + self.synchronized = False + self.delay = 0 + + # FIXME: Makes the QA hang for some reason + # raise NotImplemented + + # stop processing inputs + break + + if not self.synchronized: + log.warning(f"Processed {inp_len} samples but could not synchronize") + else: + self.delaybuf.extendleft(inp) # return data with delay out[:] = self.delaybuf[self.delay] |