make the current doppler offset estimate available

This commit is contained in:
Christoph Mayer 2019-09-24 13:31:22 +02:00
parent 95cb14d38e
commit b846571748
5 changed files with 46 additions and 10 deletions

View File

@ -34,6 +34,7 @@ class msg_proxy(gr.basic_block):
out_sig=[])
self._obj = physical_layer_object
self._quality = 0.0
self._doppler = 0.0
self._port_doppler = pmt.intern("doppler")
self.message_port_register_in(self._port_doppler)
@ -54,8 +55,9 @@ class msg_proxy(gr.basic_block):
def msg_handler_doppler(self, msg_in):
## print('-------------------- msg_handler_doppler --------------------')
iq_samples = pmt.to_python(pmt.cdr(msg_in))
msg_out = pmt.to_pmt(self._obj.get_doppler(iq_samples))
self.message_port_pub(self._port_doppler, msg_out)
doppler = self._obj.get_doppler(iq_samples)
self._doppler = doppler['doppler']
self.message_port_pub(self._port_doppler, pmt.to_pmt(doppler))
def msg_handler_frame(self, msg_in):
## print('-------------------- msg_handler_frame --------------------')
@ -82,3 +84,6 @@ class msg_proxy(gr.basic_block):
def get_quality(self):
return ('%5.1f %%' % self._quality)
def get_doppler(self):
return self._doppler

View File

@ -105,6 +105,7 @@ class PhysicalLayer(object):
self._viterbi_dec = viterbi27(0x6d, 0x4f)
self._repeat = 1
self._mode_descr = 'UNKNOWN'
self._fault_counter = 0
def get_constellations(self):
return self._constellations
@ -121,6 +122,7 @@ class PhysicalLayer(object):
success = True
if len(symbols) == 0:
self._frame_counter = -1
self._fault_counter = 0
s = self.get_preamble()
s.resize(15+len(s))
s['scramble'][-15:] = 1
@ -177,12 +179,20 @@ class PhysicalLayer(object):
tests = [np.abs(mean_s) > 0.4,
np.real(mean_s) > np.imag(mean_s)]
print('FRAME_QUALITY: ', s, mean_s, tests)
success = all(tests)
if all(tests):
self._fault_counter -= 1
else:
self._fault_counter += 1
self._fault_counter = min(11, max(0, self._fault_counter))
success = self._fault_counter < 10
if not success:
self._fault_counter = 0
return success
def get_doppler(self, iq_samples):
"""quality check and doppler estimation for preamble"""
r = {'success': False, ## -- quality flag
'use_amp_est': self._frame_counter < 0,
'doppler': 0} ## -- doppler estimate (rad/symb)
if len(iq_samples) != 0:
sps = self._sps
@ -215,10 +225,11 @@ class PhysicalLayer(object):
tt[0] = np.abs(np.vdot(t, self._preamble['symb'][0:15]))
for i in range(1,len(tt)):
tt[i] = np.abs(np.vdot(t, np.roll(M1, -SHIFTS[i-1])[0:15]))
print('XXX ', tt)
ii = np.argmax(tt)
## TODO: add a meaningful QA test
return True,ii
imax = np.argmax(tt)
test = tt[imax] / (np.sum(tt) - tt[imax]) * len(MODES)
success = test > 3
print('XXX ', test, tt)
return success,imax
def set_mode(self, _):
pass

View File

@ -309,6 +309,7 @@ class PhysicalLayer(object):
def get_doppler(self, iq_samples):
"""quality check and doppler estimation for preamble"""
r = {'success': False, ## -- quality flag
'use_amp_est': self._frame_counter < 0,
'doppler': 0} ## -- doppler estimate (rad/symb)
if len(iq_samples) != 0:
sps = self._sps

View File

@ -52,6 +52,8 @@ class PhysicalLayer(object):
self._data = self.get_data()
self._viterbi_decoder = viterbi27(0x6d, 0x4f)
self._mode_description = None
self._frame_counter = -1
self._fault_counter = 0
def set_mode(self, mode):
"""set modulation and interleaver: 'BPS/S' or 'BPS/L'"""
@ -61,6 +63,7 @@ class PhysicalLayer(object):
self._deinterleaver = Deinterleaver(DEINTERLEAVER_INCR[intl] * MODES[bps]['deintl_multiple'])
self._depuncturer = common.Depuncturer(repeat = MODES[bps]['repeat'],
puncture_pattern = MODES[bps]['punct'])
self._fault_counter = 0
def get_mode(self):
return self._mode_description
@ -82,8 +85,18 @@ class PhysicalLayer(object):
frame_description = [self._preamble,MODE_BPSK,success,False]
else: ## current frame is a preamble frame
idx = range(30,80)
idx = range(50)
z = symbols[idx]*np.conj(self._preamble['symb'][idx])
success = bool(np.sum(np.real(z)<0) < 30)
mean_z = np.mean(z)
if np.sum(np.real(z)<0) < 30 and np.real(mean_z) > np.abs(np.imag(mean_z)) and np.real(mean_z) > 0.3:
self._fault_counter -= 1
else:
self._fault_counter += 1
self._fault_counter = min(11, max(0, self._fault_counter))
success = self._fault_counter < 10
if not success:
self._frame_counter = -2
self._fault_counter = 0
frame_description = [self._data,self._mode,success,True]
self._frame_counter += 1
@ -91,6 +104,7 @@ class PhysicalLayer(object):
def get_doppler(self, iq_samples):
r = {'success': False, ## -- quality flag
'use_amp_est': self._frame_counter < 0,
'doppler': 0} ## -- doppler estimate (rad/symb)
if len(iq_samples) == 0:
return r

View File

@ -20,6 +20,7 @@
#
import importlib
import math
from gnuradio import blocks
from gnuradio import digital
from gnuradio import filter
@ -46,6 +47,7 @@ class physical_layer_driver(gr.hier_block2):
self._nB = nB
self._nF = nF
self._nW = nW
self._samp_rate = samp_rate
m = importlib.import_module('digitalhf.physical_layer.'+description_name)
self._physical_layer_driver_description = m.PhysicalLayer(sps)
@ -60,8 +62,8 @@ class physical_layer_driver(gr.hier_block2):
self._corr_est = digital.corr_est_cc(symbols = (preamble_samples.tolist()),
sps = sps,
mark_delay = preamble_offset,
threshold = 0.1,
threshold_method = 1)
threshold = 1-math.exp(-5),
threshold_method = 0)
self._doppler_correction = digitalhf.doppler_correction_cc(preamble_length, len(preamble_samples))
self._adaptive_filter = digitalhf.adaptive_dfe(sps, nB, nF, nW, mu, alpha)
self._msg_proxy = digitalhf.msg_proxy(self._physical_layer_driver_description)
@ -109,3 +111,6 @@ class physical_layer_driver(gr.hier_block2):
def get_mode(self):
return self._physical_layer_driver_description.get_mode()
def get_doppler(self):
return '%+4.1f Hz' % (self._msg_proxy.get_doppler()*self._samp_rate/(2*math.pi))