mirror of
https://github.com/hb9fxq/gr-digitalhf
synced 2024-12-22 07:09:59 +00:00
make the current doppler offset estimate available
This commit is contained in:
parent
95cb14d38e
commit
b846571748
|
@ -34,6 +34,7 @@ class msg_proxy(gr.basic_block):
|
||||||
out_sig=[])
|
out_sig=[])
|
||||||
self._obj = physical_layer_object
|
self._obj = physical_layer_object
|
||||||
self._quality = 0.0
|
self._quality = 0.0
|
||||||
|
self._doppler = 0.0
|
||||||
|
|
||||||
self._port_doppler = pmt.intern("doppler")
|
self._port_doppler = pmt.intern("doppler")
|
||||||
self.message_port_register_in(self._port_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):
|
def msg_handler_doppler(self, msg_in):
|
||||||
## print('-------------------- msg_handler_doppler --------------------')
|
## print('-------------------- msg_handler_doppler --------------------')
|
||||||
iq_samples = pmt.to_python(pmt.cdr(msg_in))
|
iq_samples = pmt.to_python(pmt.cdr(msg_in))
|
||||||
msg_out = pmt.to_pmt(self._obj.get_doppler(iq_samples))
|
doppler = self._obj.get_doppler(iq_samples)
|
||||||
self.message_port_pub(self._port_doppler, msg_out)
|
self._doppler = doppler['doppler']
|
||||||
|
self.message_port_pub(self._port_doppler, pmt.to_pmt(doppler))
|
||||||
|
|
||||||
def msg_handler_frame(self, msg_in):
|
def msg_handler_frame(self, msg_in):
|
||||||
## print('-------------------- msg_handler_frame --------------------')
|
## print('-------------------- msg_handler_frame --------------------')
|
||||||
|
@ -82,3 +84,6 @@ class msg_proxy(gr.basic_block):
|
||||||
|
|
||||||
def get_quality(self):
|
def get_quality(self):
|
||||||
return ('%5.1f %%' % self._quality)
|
return ('%5.1f %%' % self._quality)
|
||||||
|
|
||||||
|
def get_doppler(self):
|
||||||
|
return self._doppler
|
||||||
|
|
|
@ -105,6 +105,7 @@ class PhysicalLayer(object):
|
||||||
self._viterbi_dec = viterbi27(0x6d, 0x4f)
|
self._viterbi_dec = viterbi27(0x6d, 0x4f)
|
||||||
self._repeat = 1
|
self._repeat = 1
|
||||||
self._mode_descr = 'UNKNOWN'
|
self._mode_descr = 'UNKNOWN'
|
||||||
|
self._fault_counter = 0
|
||||||
|
|
||||||
def get_constellations(self):
|
def get_constellations(self):
|
||||||
return self._constellations
|
return self._constellations
|
||||||
|
@ -121,6 +122,7 @@ class PhysicalLayer(object):
|
||||||
success = True
|
success = True
|
||||||
if len(symbols) == 0:
|
if len(symbols) == 0:
|
||||||
self._frame_counter = -1
|
self._frame_counter = -1
|
||||||
|
self._fault_counter = 0
|
||||||
s = self.get_preamble()
|
s = self.get_preamble()
|
||||||
s.resize(15+len(s))
|
s.resize(15+len(s))
|
||||||
s['scramble'][-15:] = 1
|
s['scramble'][-15:] = 1
|
||||||
|
@ -177,12 +179,20 @@ class PhysicalLayer(object):
|
||||||
tests = [np.abs(mean_s) > 0.4,
|
tests = [np.abs(mean_s) > 0.4,
|
||||||
np.real(mean_s) > np.imag(mean_s)]
|
np.real(mean_s) > np.imag(mean_s)]
|
||||||
print('FRAME_QUALITY: ', s, mean_s, tests)
|
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
|
return success
|
||||||
|
|
||||||
def get_doppler(self, iq_samples):
|
def get_doppler(self, iq_samples):
|
||||||
"""quality check and doppler estimation for preamble"""
|
"""quality check and doppler estimation for preamble"""
|
||||||
r = {'success': False, ## -- quality flag
|
r = {'success': False, ## -- quality flag
|
||||||
|
'use_amp_est': self._frame_counter < 0,
|
||||||
'doppler': 0} ## -- doppler estimate (rad/symb)
|
'doppler': 0} ## -- doppler estimate (rad/symb)
|
||||||
if len(iq_samples) != 0:
|
if len(iq_samples) != 0:
|
||||||
sps = self._sps
|
sps = self._sps
|
||||||
|
@ -215,10 +225,11 @@ class PhysicalLayer(object):
|
||||||
tt[0] = np.abs(np.vdot(t, self._preamble['symb'][0:15]))
|
tt[0] = np.abs(np.vdot(t, self._preamble['symb'][0:15]))
|
||||||
for i in range(1,len(tt)):
|
for i in range(1,len(tt)):
|
||||||
tt[i] = np.abs(np.vdot(t, np.roll(M1, -SHIFTS[i-1])[0:15]))
|
tt[i] = np.abs(np.vdot(t, np.roll(M1, -SHIFTS[i-1])[0:15]))
|
||||||
print('XXX ', tt)
|
imax = np.argmax(tt)
|
||||||
ii = np.argmax(tt)
|
test = tt[imax] / (np.sum(tt) - tt[imax]) * len(MODES)
|
||||||
## TODO: add a meaningful QA test
|
success = test > 3
|
||||||
return True,ii
|
print('XXX ', test, tt)
|
||||||
|
return success,imax
|
||||||
|
|
||||||
def set_mode(self, _):
|
def set_mode(self, _):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -309,6 +309,7 @@ class PhysicalLayer(object):
|
||||||
def get_doppler(self, iq_samples):
|
def get_doppler(self, iq_samples):
|
||||||
"""quality check and doppler estimation for preamble"""
|
"""quality check and doppler estimation for preamble"""
|
||||||
r = {'success': False, ## -- quality flag
|
r = {'success': False, ## -- quality flag
|
||||||
|
'use_amp_est': self._frame_counter < 0,
|
||||||
'doppler': 0} ## -- doppler estimate (rad/symb)
|
'doppler': 0} ## -- doppler estimate (rad/symb)
|
||||||
if len(iq_samples) != 0:
|
if len(iq_samples) != 0:
|
||||||
sps = self._sps
|
sps = self._sps
|
||||||
|
|
|
@ -52,6 +52,8 @@ class PhysicalLayer(object):
|
||||||
self._data = self.get_data()
|
self._data = self.get_data()
|
||||||
self._viterbi_decoder = viterbi27(0x6d, 0x4f)
|
self._viterbi_decoder = viterbi27(0x6d, 0x4f)
|
||||||
self._mode_description = None
|
self._mode_description = None
|
||||||
|
self._frame_counter = -1
|
||||||
|
self._fault_counter = 0
|
||||||
|
|
||||||
def set_mode(self, mode):
|
def set_mode(self, mode):
|
||||||
"""set modulation and interleaver: 'BPS/S' or 'BPS/L'"""
|
"""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._deinterleaver = Deinterleaver(DEINTERLEAVER_INCR[intl] * MODES[bps]['deintl_multiple'])
|
||||||
self._depuncturer = common.Depuncturer(repeat = MODES[bps]['repeat'],
|
self._depuncturer = common.Depuncturer(repeat = MODES[bps]['repeat'],
|
||||||
puncture_pattern = MODES[bps]['punct'])
|
puncture_pattern = MODES[bps]['punct'])
|
||||||
|
self._fault_counter = 0
|
||||||
|
|
||||||
def get_mode(self):
|
def get_mode(self):
|
||||||
return self._mode_description
|
return self._mode_description
|
||||||
|
@ -82,8 +85,18 @@ class PhysicalLayer(object):
|
||||||
frame_description = [self._preamble,MODE_BPSK,success,False]
|
frame_description = [self._preamble,MODE_BPSK,success,False]
|
||||||
else: ## current frame is a preamble frame
|
else: ## current frame is a preamble frame
|
||||||
idx = range(30,80)
|
idx = range(30,80)
|
||||||
|
idx = range(50)
|
||||||
z = symbols[idx]*np.conj(self._preamble['symb'][idx])
|
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]
|
frame_description = [self._data,self._mode,success,True]
|
||||||
|
|
||||||
self._frame_counter += 1
|
self._frame_counter += 1
|
||||||
|
@ -91,6 +104,7 @@ class PhysicalLayer(object):
|
||||||
|
|
||||||
def get_doppler(self, iq_samples):
|
def get_doppler(self, iq_samples):
|
||||||
r = {'success': False, ## -- quality flag
|
r = {'success': False, ## -- quality flag
|
||||||
|
'use_amp_est': self._frame_counter < 0,
|
||||||
'doppler': 0} ## -- doppler estimate (rad/symb)
|
'doppler': 0} ## -- doppler estimate (rad/symb)
|
||||||
if len(iq_samples) == 0:
|
if len(iq_samples) == 0:
|
||||||
return r
|
return r
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import importlib
|
import importlib
|
||||||
|
import math
|
||||||
from gnuradio import blocks
|
from gnuradio import blocks
|
||||||
from gnuradio import digital
|
from gnuradio import digital
|
||||||
from gnuradio import filter
|
from gnuradio import filter
|
||||||
|
@ -46,6 +47,7 @@ class physical_layer_driver(gr.hier_block2):
|
||||||
self._nB = nB
|
self._nB = nB
|
||||||
self._nF = nF
|
self._nF = nF
|
||||||
self._nW = nW
|
self._nW = nW
|
||||||
|
self._samp_rate = samp_rate
|
||||||
|
|
||||||
m = importlib.import_module('digitalhf.physical_layer.'+description_name)
|
m = importlib.import_module('digitalhf.physical_layer.'+description_name)
|
||||||
self._physical_layer_driver_description = m.PhysicalLayer(sps)
|
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()),
|
self._corr_est = digital.corr_est_cc(symbols = (preamble_samples.tolist()),
|
||||||
sps = sps,
|
sps = sps,
|
||||||
mark_delay = preamble_offset,
|
mark_delay = preamble_offset,
|
||||||
threshold = 0.1,
|
threshold = 1-math.exp(-5),
|
||||||
threshold_method = 1)
|
threshold_method = 0)
|
||||||
self._doppler_correction = digitalhf.doppler_correction_cc(preamble_length, len(preamble_samples))
|
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._adaptive_filter = digitalhf.adaptive_dfe(sps, nB, nF, nW, mu, alpha)
|
||||||
self._msg_proxy = digitalhf.msg_proxy(self._physical_layer_driver_description)
|
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):
|
def get_mode(self):
|
||||||
return self._physical_layer_driver_description.get_mode()
|
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))
|
||||||
|
|
Loading…
Reference in a new issue