mirror of
https://github.com/hb9fxq/gr-digitalhf
synced 2024-12-22 15:10:00 +00:00
preparations for XOR scrambling
work on 110C mode (intermediate)
This commit is contained in:
parent
be31566ff1
commit
6cf9752275
|
@ -164,7 +164,7 @@
|
||||||
</param>
|
</param>
|
||||||
<param>
|
<param>
|
||||||
<key>value</key>
|
<key>value</key>
|
||||||
<value>'600/L'</value>
|
<value>'1200/L'</value>
|
||||||
</param>
|
</param>
|
||||||
<param>
|
<param>
|
||||||
<key>_enabled</key>
|
<key>_enabled</key>
|
||||||
|
@ -240,7 +240,7 @@
|
||||||
</param>
|
</param>
|
||||||
<param>
|
<param>
|
||||||
<key>options</key>
|
<key>options</key>
|
||||||
<value>['2400/L', '1200/L', '600/L', '300/L', '150/L', '75/L']</value>
|
<value>['2400/L', '1200/L', '600/L', '300/L', '150/L', '75/L', '2400/S', '1200/S', '600/S', '300/S', '150/S', '75/S']</value>
|
||||||
</param>
|
</param>
|
||||||
<param>
|
<param>
|
||||||
<key>orient</key>
|
<key>orient</key>
|
||||||
|
@ -877,11 +877,11 @@
|
||||||
</param>
|
</param>
|
||||||
<param>
|
<param>
|
||||||
<key>file</key>
|
<key>file</key>
|
||||||
<value>/Users/chm/Software/gr-digitalhf/examples/on5kq.ddns.net_2019-03-20T12_49_38Z_2381.40_iq.wav</value>
|
<value>/Users/chm/Downloads/sdr.loginto.me_2019-05-14T13_46_37Z_7938.80_iq.wav</value>
|
||||||
</param>
|
</param>
|
||||||
<param>
|
<param>
|
||||||
<key>_coordinate</key>
|
<key>_coordinate</key>
|
||||||
<value>(10, 154)</value>
|
<value>(21, 154)</value>
|
||||||
</param>
|
</param>
|
||||||
<param>
|
<param>
|
||||||
<key>_rotation</key>
|
<key>_rotation</key>
|
||||||
|
|
|
@ -83,6 +83,7 @@ adaptive_dfe_impl::adaptive_dfe_impl(int sps, // samples per symbol
|
||||||
, _constellation_index()
|
, _constellation_index()
|
||||||
, _symbols()
|
, _symbols()
|
||||||
, _scramble()
|
, _scramble()
|
||||||
|
, _scramble_xor()
|
||||||
, _descrambled_symbols()
|
, _descrambled_symbols()
|
||||||
, _symbol_counter(0)
|
, _symbol_counter(0)
|
||||||
, _save_soft_decisions(false)
|
, _save_soft_decisions(false)
|
||||||
|
@ -280,7 +281,12 @@ gr_complex adaptive_dfe_impl::filter(gr_complex const* start, gr_complex const*
|
||||||
float const err = std::abs(descrambled_filter_output - descrambled_symbol);
|
float const err = std::abs(descrambled_filter_output - descrambled_symbol);
|
||||||
std::vector<float> const soft_dec = constell->calc_soft_dec
|
std::vector<float> const soft_dec = constell->calc_soft_dec
|
||||||
(descrambled_filter_output, _npwr[_constellation_index].filter(err));
|
(descrambled_filter_output, _npwr[_constellation_index].filter(err));
|
||||||
std::copy(soft_dec.begin(), soft_dec.end(), std::back_inserter<std::vector<float> >(_vec_soft_decisions));
|
// std::cout << "SD: " << descrambled_filter_output << " : ";
|
||||||
|
for (int j=0, m=soft_dec.size(); j<m; ++j) {
|
||||||
|
_vec_soft_decisions.push_back(soft_dec[j] * _scramble_xor[_symbol_counter][j]);
|
||||||
|
// std::cout << " " << _vec_soft_decisions.back();
|
||||||
|
}
|
||||||
|
// std::cout << std::endl;
|
||||||
}
|
}
|
||||||
known_symbol = _scramble[_symbol_counter] * descrambled_symbol;
|
known_symbol = _scramble[_symbol_counter] * descrambled_symbol;
|
||||||
}
|
}
|
||||||
|
@ -289,6 +295,8 @@ gr_complex adaptive_dfe_impl::filter(gr_complex const* start, gr_complex const*
|
||||||
if (is_known || update_taps) {
|
if (is_known || update_taps) {
|
||||||
// (3a) update of adaptive filter taps
|
// (3a) update of adaptive filter taps
|
||||||
gr_complex const err = filter_output - known_symbol;
|
gr_complex const err = filter_output - known_symbol;
|
||||||
|
if (std::abs(err)>0.5)
|
||||||
|
std::cout << "err= " << std::abs(err) << std::endl;
|
||||||
// taps_samples
|
// taps_samples
|
||||||
for (int j=0; j<_nB+_nF+1; ++j) {
|
for (int j=0; j<_nB+_nF+1; ++j) {
|
||||||
_last_taps_samples[j] = _taps_samples[j];
|
_last_taps_samples[j] = _taps_samples[j];
|
||||||
|
@ -311,7 +319,7 @@ gr_complex adaptive_dfe_impl::filter(gr_complex const* start, gr_complex const*
|
||||||
for (int j=_nB+1-2*_sps; j<_nB+1+2*_sps+1; ++j)
|
for (int j=_nB+1-2*_sps; j<_nB+1+2*_sps+1; ++j)
|
||||||
acc += std::conj(_last_taps_samples[j]) * _taps_samples[j];
|
acc += std::conj(_last_taps_samples[j]) * _taps_samples[j];
|
||||||
float const frequency_err = gr::fast_atan2f(acc)/(1+0*_num_samples_since_filter_update); // frequency error (rad/sample)
|
float const frequency_err = gr::fast_atan2f(acc)/(1+0*_num_samples_since_filter_update); // frequency error (rad/sample)
|
||||||
std::cout << "frequency_err " << frequency_err << " " << _num_samples_since_filter_update << std::endl;
|
GR_LOG_DEBUG(d_logger, str(boost::format("frequency_err= %f %d") % frequency_err % _num_samples_since_filter_update));
|
||||||
_control_loop.advance_loop(frequency_err);
|
_control_loop.advance_loop(frequency_err);
|
||||||
_control_loop.phase_wrap();
|
_control_loop.phase_wrap();
|
||||||
_control_loop.frequency_limit();
|
_control_loop.frequency_limit();
|
||||||
|
@ -390,8 +398,7 @@ void adaptive_dfe_impl::update_constellations(pmt::pmt_t data) {
|
||||||
int const n = pmt::length(data);
|
int const n = pmt::length(data);
|
||||||
_constellations.resize(n);
|
_constellations.resize(n);
|
||||||
_npwr.resize(n);
|
_npwr.resize(n);
|
||||||
std::cout << "adaptive_dfe_impl::update_constellations " << data << std::endl;
|
GR_LOG_DEBUG(d_logger, str(boost::format("update_constellations %s n=%d") % data % n));
|
||||||
std::cout << "adaptive_dfe_impl::update_constellations n=" << n << std::endl;
|
|
||||||
unsigned int const rotational_symmetry = 0;
|
unsigned int const rotational_symmetry = 0;
|
||||||
unsigned int const dimensionality = 1;
|
unsigned int const dimensionality = 1;
|
||||||
|
|
||||||
|
@ -415,6 +422,18 @@ void adaptive_dfe_impl::update_frame_info(pmt::pmt_t data)
|
||||||
_constellation_index = pmt::to_long(pmt::dict_ref(data, pmt::intern("constellation_idx"), pmt::PMT_NIL));
|
_constellation_index = pmt::to_long(pmt::dict_ref(data, pmt::intern("constellation_idx"), pmt::PMT_NIL));
|
||||||
_save_soft_decisions = pmt::to_bool(pmt::dict_ref(data, pmt::intern("save_soft_dec"), pmt::PMT_F));
|
_save_soft_decisions = pmt::to_bool(pmt::dict_ref(data, pmt::intern("save_soft_dec"), pmt::PMT_F));
|
||||||
bool const do_continue = pmt::to_bool(pmt::dict_ref(data, pmt::intern("do_continue"), pmt::PMT_F));
|
bool const do_continue = pmt::to_bool(pmt::dict_ref(data, pmt::intern("do_continue"), pmt::PMT_F));
|
||||||
|
|
||||||
|
// make table +-1
|
||||||
|
std::vector<std::uint8_t> const scr_xor = pmt::u8vector_elements(pmt::dict_ref(data, pmt::intern("scramble_xor"), pmt::PMT_NIL));
|
||||||
|
_scramble_xor.resize(scr_xor.size());
|
||||||
|
gr::digital::constellation_sptr constell = _constellations[_constellation_index];
|
||||||
|
for (int i=0, n=scr_xor.size(); i<n; ++i) {
|
||||||
|
for (int j=0, m=constell->bits_per_symbol(); j<m; ++j) {
|
||||||
|
_scramble_xor[i][m-j-1] = 1 - 2*bool(scr_xor[i] & (1<<j));
|
||||||
|
// GR_LOG_DEBUG(d_logger, str(boost::format("XOR %3d %3d %d") % i % j % _scramble_xor[i][j]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert(_symbols.size() == _scramble.size());
|
assert(_symbols.size() == _scramble.size());
|
||||||
_descrambled_symbols.resize(_symbols.size());
|
_descrambled_symbols.resize(_symbols.size());
|
||||||
_vec_soft_decisions.clear();
|
_vec_soft_decisions.clear();
|
||||||
|
|
|
@ -81,7 +81,8 @@ private:
|
||||||
int _npwr_max_time_constant;
|
int _npwr_max_time_constant;
|
||||||
int _constellation_index;
|
int _constellation_index;
|
||||||
std::vector<gr_complex> _symbols;
|
std::vector<gr_complex> _symbols;
|
||||||
std::vector<gr_complex> _scramble;
|
std::vector<gr_complex> _scramble; // PSK-8 scramble symbols
|
||||||
|
std::vector<std::array<int,8> > _scramble_xor; // signs for XOR scrambling
|
||||||
std::vector<gr_complex> _descrambled_symbols;
|
std::vector<gr_complex> _descrambled_symbols;
|
||||||
int _symbol_counter;
|
int _symbol_counter;
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,7 @@ class msg_proxy(gr.basic_block):
|
||||||
msg_out = pmt.make_dict()
|
msg_out = pmt.make_dict()
|
||||||
msg_out = pmt.dict_add(msg_out, pmt.intern('symb'), pmt.to_pmt(symb['symb']))
|
msg_out = pmt.dict_add(msg_out, pmt.intern('symb'), pmt.to_pmt(symb['symb']))
|
||||||
msg_out = pmt.dict_add(msg_out, pmt.intern('scramble'), pmt.to_pmt(symb['scramble']))
|
msg_out = pmt.dict_add(msg_out, pmt.intern('scramble'), pmt.to_pmt(symb['scramble']))
|
||||||
|
msg_out = pmt.dict_add(msg_out, pmt.intern('scramble_xor'), pmt.to_pmt(symb['scramble_xor']))
|
||||||
msg_out = pmt.dict_add(msg_out, pmt.intern('constellation_idx'), pmt.to_pmt(constellation_idx))
|
msg_out = pmt.dict_add(msg_out, pmt.intern('constellation_idx'), pmt.to_pmt(constellation_idx))
|
||||||
msg_out = pmt.dict_add(msg_out, pmt.intern('do_continue'), pmt.to_pmt(np.bool(do_continue)))
|
msg_out = pmt.dict_add(msg_out, pmt.intern('do_continue'), pmt.to_pmt(np.bool(do_continue)))
|
||||||
msg_out = pmt.dict_add(msg_out, pmt.intern('save_soft_dec'), pmt.to_pmt(np.bool(save_soft_dec)))
|
msg_out = pmt.dict_add(msg_out, pmt.intern('save_soft_dec'), pmt.to_pmt(np.bool(save_soft_dec)))
|
||||||
|
|
|
@ -199,9 +199,7 @@ class PhysicalLayer(object):
|
||||||
self._frame_counter = 0
|
self._frame_counter = 0
|
||||||
scramble_for_frame = common.n_psk(8, np.array([self._scr_data.next()
|
scramble_for_frame = common.n_psk(8, np.array([self._scr_data.next()
|
||||||
for _ in range(self._frame_len)]))
|
for _ in range(self._frame_len)]))
|
||||||
a = np.array(zip(scramble_for_frame,
|
a = common.make_scr(scramble_for_frame, scramble_for_frame)
|
||||||
scramble_for_frame),
|
|
||||||
common.SYMB_SCRAMBLE_DTYPE)
|
|
||||||
n_unknown = self._mode['unknown']
|
n_unknown = self._mode['unknown']
|
||||||
a['symb'][0:n_unknown] = 0
|
a['symb'][0:n_unknown] = 0
|
||||||
if self._mode['known'] != 0 and self._frame_counter >= self._num_frames_per_block-2:
|
if self._mode['known'] != 0 and self._frame_counter >= self._num_frames_per_block-2:
|
||||||
|
@ -296,10 +294,8 @@ class PhysicalLayer(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_preamble():
|
def get_preamble():
|
||||||
"""preamble symbols + scrambler"""
|
"""preamble symbols + scrambler"""
|
||||||
return np.array(zip(PRE_SCRAMBLE*PRE_SYMBOLS,
|
return common.make_scr(PRE_SCRAMBLE*PRE_SYMBOLS,
|
||||||
PRE_SCRAMBLE),
|
PRE_SCRAMBLE)
|
||||||
common.SYMB_SCRAMBLE_DTYPE)
|
|
||||||
|
|
||||||
def get_preamble_z(self):
|
def get_preamble_z(self):
|
||||||
"""preamble symbols for preamble correlation"""
|
"""preamble symbols for preamble correlation"""
|
||||||
a = PhysicalLayer.get_preamble()
|
a = PhysicalLayer.get_preamble()
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import common
|
import common
|
||||||
|
from digitalhf.digitalhf_swig import viterbi27
|
||||||
|
|
||||||
## ---- constellations -----------------------------------------------------------
|
## ---- constellations -----------------------------------------------------------
|
||||||
BPSK=np.array(zip(np.exp(2j*np.pi*np.arange(2)/2), [0,1]), common.CONST_DTYPE)
|
BPSK=np.array(zip(np.exp(2j*np.pi*np.arange(2)/2), [0,1]), common.CONST_DTYPE)
|
||||||
QPSK=np.array(zip(np.exp(2j*np.pi*np.arange(4)/4), [0,1,3,2]), common.CONST_DTYPE)
|
QPSK=np.array(zip(np.exp(2j*np.pi*np.arange(4)/4), [0,1,3,2]), common.CONST_DTYPE)
|
||||||
PSK8=np.array(zip(np.exp(2j*np.pi*np.arange(8)/8), [0,1,3,2,7,6,4,5]), common.CONST_DTYPE)
|
PSK8=np.array(zip(np.exp(2j*np.pi*np.arange(8)/8), [1,0,2,3,7,6,4,5]), common.CONST_DTYPE)
|
||||||
QAM16=np.array(
|
QAM16=np.array(
|
||||||
zip([+0.866025+0.500000j, 0.500000+0.866025j, 1.000000+0.000000j, 0.258819+0.258819j,
|
zip([+0.866025+0.500000j, 0.500000+0.866025j, 1.000000+0.000000j, 0.258819+0.258819j,
|
||||||
-0.500000+0.866025j, 0.000000+1.000000j, -0.866025+0.500000j, -0.258819+0.258819j,
|
-0.500000+0.866025j, 0.000000+1.000000j, -0.866025+0.500000j, -0.258819+0.258819j,
|
||||||
|
@ -104,29 +105,93 @@ MINI_PROBE=[common.n_psk(8, np.array([0,0,0,0,0,2,4,6,0,4,0,4,0,6,4,2,0,0,0,0,0,
|
||||||
TO_DIBIT=[(0,0),(0,1),(1,1),(1,0)]
|
TO_DIBIT=[(0,0),(0,1),(1,1),(1,0)]
|
||||||
|
|
||||||
## ---- rate -------------------------------------------------------------------
|
## ---- rate -------------------------------------------------------------------
|
||||||
TO_RATE={(0,0,0): {'baud': 0, 'bits_per_symbol': 0}, ## reserved
|
TO_RATE={(0,0,0): {'baud': '--------', 'bits_per_symbol': 0}, ## reserved
|
||||||
(0,0,1): {'baud': 3200, 'bits_per_symbol': 2, 'ci': MODE_QPSK},
|
(0,0,1): {'baud': '3200 bps', 'bits_per_symbol': 2, 'ci': MODE_QPSK},
|
||||||
(0,1,0): {'baud': 4800, 'bits_per_symbol': 3, 'ci': MODE_8PSK},
|
(0,1,0): {'baud': '4800 bps', 'bits_per_symbol': 3, 'ci': MODE_8PSK},
|
||||||
(0,1,1): {'baud': 6400, 'bits_per_symbol': 4, 'ci': MODE_16QAM},
|
(0,1,1): {'baud': '6400 bps', 'bits_per_symbol': 4, 'ci': MODE_16QAM},
|
||||||
(1,0,0): {'baud': 8000, 'bits_per_symbol': 5, 'ci': MODE_32QAM},
|
(1,0,0): {'baud': '8000 bps', 'bits_per_symbol': 5, 'ci': MODE_32QAM},
|
||||||
(1,0,1): {'baud': 9600, 'bits_per_symbol': 6, 'ci': MODE_64QAM},
|
(1,0,1): {'baud': '9600 bps', 'bits_per_symbol': 6, 'ci': MODE_64QAM},
|
||||||
(1,1,0): {'baud':12800, 'bits_per_symbol': 6, 'ci': MODE_64QAM},
|
(1,1,0): {'baud':'12800 bps', 'bits_per_symbol': 6, 'ci': MODE_64QAM},
|
||||||
(1,1,1): {'baud': 0, 'bits_per_symbol': 0}} ## reserved
|
(1,1,1): {'baud': '--------', 'bits_per_symbol': 0}} ## reserved
|
||||||
|
|
||||||
## ---- interleaver ------------------------------------------------------------
|
## ---- interleaver ------------------------------------------------------------
|
||||||
TO_INTERLEAVER={(0,0,0): {'frames': -1, 'name': 'illegal'},
|
TO_INTERLEAVER={(0,0,0): {'frames': -1, 'id': '--', 'name': 'illegal'},
|
||||||
(0,0,1): {'frames': 1, 'name': 'Ultra Short (US)'},
|
(0,0,1): {'frames': 1, 'id': 'US', 'name': 'Ultra Short'},
|
||||||
(0,1,0): {'frames': 3, 'name': 'Very Short (VS)'},
|
(0,1,0): {'frames': 3, 'id': 'VS', 'name': 'Very Short'},
|
||||||
(0,1,1): {'frames': 9, 'name': 'Short (S)'},
|
(0,1,1): {'frames': 9, 'id': 'S', 'name': 'Short'},
|
||||||
(1,0,0): {'frames': 18, 'name': 'Medium (M)'},
|
(1,0,0): {'frames': 18, 'id': 'M', 'name': 'Medium'},
|
||||||
(1,0,1): {'frames': 36, 'name': 'Long (L)'},
|
(1,0,1): {'frames': 36, 'id': 'L', 'name': 'Long'},
|
||||||
(1,1,0): {'frames': 72, 'name': 'very Long (VL)'},
|
(1,1,0): {'frames': 72, 'id': 'VL', 'name': 'Very Long'},
|
||||||
(1,1,1): {'frames': -1, 'name': 'illegal'}}
|
(1,1,1): {'frames': -1, 'id': '--', 'name': 'illegal'}}
|
||||||
|
|
||||||
|
MP_COUNTER=[(0,0,1), ## 1st
|
||||||
|
(0,1,0), ## 2nd
|
||||||
|
(0,1,1), ## 3rd
|
||||||
|
(1,0,0)] ## 4th
|
||||||
|
|
||||||
|
## ---- interleaver size
|
||||||
|
INTL_SIZE = { ## 1 3 9 18 36 72
|
||||||
|
'--------': {'US': 0, 'VS': 0, 'S': 0, 'M': 0, 'L': 0, 'VL': 0},
|
||||||
|
'3200 bps': {'US': 512, 'VS': 1536, 'S': 4608, 'M': 9216, 'L': 18432, 'VL': 36864},
|
||||||
|
'4800 bps': {'US': 768, 'VS': 2304, 'S': 6912, 'M': 13824, 'L': 27648, 'VL': 55296},
|
||||||
|
'6400 bps': {'US': 1024, 'VS': 3072, 'S': 9216, 'M': 18432, 'L': 36864, 'VL': 73728},
|
||||||
|
'8000 bps': {'US': 1280, 'VS': 3840, 'S': 11520, 'M': 23040, 'L': 46080, 'VL': 92160},
|
||||||
|
'9600 bps': {'US': 1536, 'VS': 4608, 'S': 13824, 'M': 27648, 'L': 55296, 'VL': 110592}
|
||||||
|
}
|
||||||
|
|
||||||
|
## ---- interleaver increment
|
||||||
|
INTL_INCR = { ## 1 3 9 18 36 72
|
||||||
|
'--------': {'US': 0, 'VS': 0, 'S': 0, 'M': 0, 'L': 0, 'VL': 0},
|
||||||
|
'3200 bps': {'US': 97, 'VS': 229, 'S': 805, 'M': 1393, 'L': 3281, 'VL': 6985},
|
||||||
|
'4800 bps': {'US': 145, 'VS': 361, 'S': 1045, 'M': 2089, 'L': 5137, 'VL': 10273},
|
||||||
|
'6400 bps': {'US': 189, 'VS': 481, 'S': 1393, 'M': 3281, 'L': 6985, 'VL': 11141},
|
||||||
|
'8000 bps': {'US': 201, 'VS': 601, 'S': 1741, 'M': 3481, 'L': 8561, 'VL': 14441},
|
||||||
|
'9600 bps': {'US': 229, 'VS': 805, 'S': 2089, 'M': 5137, 'L': 10273, 'VL': 17329}
|
||||||
|
}
|
||||||
|
|
||||||
|
## ---- deinterleaver+depuncturer
|
||||||
|
class DeIntl_DePunct(object):
|
||||||
|
"""deinterleave"""
|
||||||
|
def __init__(self, size, incr):
|
||||||
|
self._size = size
|
||||||
|
self._i = 0
|
||||||
|
self._array = np.zeros(size, dtype=np.float32)
|
||||||
|
self._idx = np.mod(incr*np.arange(size, dtype=np.uint32), size)
|
||||||
|
print('deinterleaver: ', size, incr, self._idx[0:100])
|
||||||
|
|
||||||
|
def fetch(self, a):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def load(self, a):
|
||||||
|
n = len(a)
|
||||||
|
i = self._i
|
||||||
|
if i==0:
|
||||||
|
self._array[:] = 0
|
||||||
|
print('deinterleaver load buffer:', i,len(self._array),n)
|
||||||
|
assert(i+n <= self._size)
|
||||||
|
self._array[i:i+n] = a
|
||||||
|
self._i += n
|
||||||
|
result = np.zeros(0, dtype=np.float64)
|
||||||
|
if self._i == self._size:
|
||||||
|
print('==== TEST ====', self._array)
|
||||||
|
#tmp = np.zeros(self._size, dtype=np.float32)
|
||||||
|
tmp = self._array[self._idx]
|
||||||
|
result = np.zeros(self._size*6//4, dtype=np.float64)
|
||||||
|
assert(len(result[0::6]) == len(tmp[0::4]))
|
||||||
|
assert(len(result[1::6]) == len(tmp[1::4]))
|
||||||
|
assert(len(result[2::6]) == len(tmp[2::4]))
|
||||||
|
assert(len(result[5::6]) == len(tmp[3::4]))
|
||||||
|
result[0::6] = tmp[0::4]
|
||||||
|
result[1::6] = tmp[1::4]
|
||||||
|
result[2::6] = tmp[2::4]
|
||||||
|
result[3::6] = 0
|
||||||
|
result[4::6] = 0
|
||||||
|
result[5::6] = tmp[3::4]
|
||||||
|
print('==================== interleaver is full! ====================',
|
||||||
|
len(result[0::6]), len(tmp[0::4]), np.sum(result==0))
|
||||||
|
self._i = 0
|
||||||
|
return result
|
||||||
|
|
||||||
MP_COUNTER=[(0,0,1),
|
|
||||||
(0,1,0),
|
|
||||||
(0,1,1),
|
|
||||||
(1,0,0)]
|
|
||||||
|
|
||||||
## ---- physcal layer class -----------------------------------------------------
|
## ---- physcal layer class -----------------------------------------------------
|
||||||
class PhysicalLayer(object):
|
class PhysicalLayer(object):
|
||||||
|
@ -138,7 +203,8 @@ class PhysicalLayer(object):
|
||||||
self._frame_counter = -2
|
self._frame_counter = -2
|
||||||
self._constellations = [BPSK, QPSK, PSK8, QAM16, QAM32, QAM64]
|
self._constellations = [BPSK, QPSK, PSK8, QAM16, QAM32, QAM64]
|
||||||
self._preamble = self.get_preamble()
|
self._preamble = self.get_preamble()
|
||||||
self._interleaver_length = 72 ## set in decode_reinserted preamble to the actual value
|
self._scramble = ScrambleData()
|
||||||
|
self._viterbi_decoder = viterbi27(0x6d, 0x4f)
|
||||||
|
|
||||||
def get_constellations(self):
|
def get_constellations(self):
|
||||||
return self._constellations
|
return self._constellations
|
||||||
|
@ -153,6 +219,8 @@ class PhysicalLayer(object):
|
||||||
print('-------------------- get_frame --------------------', self._frame_counter)
|
print('-------------------- get_frame --------------------', self._frame_counter)
|
||||||
success = True
|
success = True
|
||||||
if self._frame_counter == -2: ## ---- preamble
|
if self._frame_counter == -2: ## ---- preamble
|
||||||
|
self._deintl_depunct = None
|
||||||
|
self._mode = {}
|
||||||
self._preamble_offset = 0
|
self._preamble_offset = 0
|
||||||
self._frame_counter += 1
|
self._frame_counter += 1
|
||||||
return [self._preamble,MODE_BPSK,success,False]
|
return [self._preamble,MODE_BPSK,success,False]
|
||||||
|
@ -215,46 +283,67 @@ class PhysicalLayer(object):
|
||||||
|
|
||||||
def decode_reinserted_preamble(self, symbols):
|
def decode_reinserted_preamble(self, symbols):
|
||||||
## decode D0,D1,D2
|
## decode D0,D1,D2
|
||||||
|
success = True
|
||||||
z = np.array([np.mean(symbols[-71+i*13:-71+(i+1)*13]) for i in range(3)])
|
z = np.array([np.mean(symbols[-71+i*13:-71+(i+1)*13]) for i in range(3)])
|
||||||
print('decode_reinserted_preamble', symbols[0:-71], symbols[-71:-71+3*13], symbols[-71+4*13:], z)
|
if np.mean(np.abs(z)) < 0.4:
|
||||||
|
return False
|
||||||
|
print('decode_reinserted_preamble',
|
||||||
|
'\nHH', symbols[0:-71],
|
||||||
|
'\nD0', symbols[-71 :-71+13],
|
||||||
|
'\nD1', symbols[-71+13:-71+26],
|
||||||
|
'\nD2', symbols[-71+26:-71+39],
|
||||||
|
'\nTT', symbols[-71+4*13:], z)
|
||||||
d0d1d2 = map(np.uint8, np.mod(np.round(np.angle(z)/np.pi*2),4))
|
d0d1d2 = map(np.uint8, np.mod(np.round(np.angle(z)/np.pi*2),4))
|
||||||
dibits = [TO_DIBIT[idx] for idx in d0d1d2]
|
dibits = [TO_DIBIT[idx] for idx in d0d1d2]
|
||||||
self._mode = {'rate': tuple([x[0] for x in dibits]),
|
mode = {'rate': tuple([x[0] for x in dibits]),
|
||||||
'interleaver': tuple([x[1] for x in dibits])}
|
'interleaver': tuple([x[1] for x in dibits])}
|
||||||
print('======== rate,interleaver:',
|
if self._mode != {}:
|
||||||
TO_RATE[self._mode['rate']],
|
success = (mode == self._mode)
|
||||||
TO_INTERLEAVER[self._mode['interleaver']])
|
if not success:
|
||||||
self._interleaver_length = TO_INTERLEAVER[self._mode['interleaver']]['frames']
|
return success
|
||||||
rate_info = TO_RATE[self._mode['rate']]
|
self._mode = mode
|
||||||
print('rate_info', rate_info)
|
self._rate_info = rate_info = TO_RATE[self._mode['rate']]
|
||||||
|
self._intl_info = intl_info = TO_INTERLEAVER[self._mode['interleaver']]
|
||||||
|
|
||||||
|
print('======== rate,interleaver:', rate_info, intl_info)
|
||||||
|
self._interleaver_frames = intl_info['frames']
|
||||||
|
baud = rate_info['baud']
|
||||||
|
intl_id = intl_info['id']
|
||||||
|
intl_size = INTL_SIZE[baud][intl_id]
|
||||||
|
intl_incr = INTL_INCR[baud][intl_id]
|
||||||
|
if self._deintl_depunct == None:
|
||||||
|
self._deintl_depunct = DeIntl_DePunct(size=intl_size,
|
||||||
|
incr=intl_incr)
|
||||||
self._constellation_index = rate_info['ci']
|
self._constellation_index = rate_info['ci']
|
||||||
print('constellation index', self._constellation_index)
|
print('constellation index', self._constellation_index)
|
||||||
scr = ScrambleData()
|
self._scramble.reset()
|
||||||
iscr = [scr.next(rate_info['bits_per_symbol']) for _ in range(256)]
|
num_bits = max(3, rate_info['bits_per_symbol'])
|
||||||
if rate_info['ci'] > MODE_8PSK:
|
iscr = np.array([self._scramble.next(num_bits) for _ in range(256)],
|
||||||
|
dtype=np.uint8)
|
||||||
|
print('iscr=', iscr)
|
||||||
self._data_scramble = np.ones (256, dtype=np.complex64)
|
self._data_scramble = np.ones (256, dtype=np.complex64)
|
||||||
|
self._data_scramble_xor = np.zeros(256, dtype=np.uint8)
|
||||||
|
if rate_info['ci'] > MODE_8PSK:
|
||||||
|
self._data_scramble_xor = iscr
|
||||||
else:
|
else:
|
||||||
constell = self._constellations[rate_info['ci']]
|
self._data_scramble = common.n_psk(8, iscr)
|
||||||
self._data_scramble = constell[iscr]['points']
|
|
||||||
success = True ## TODO
|
|
||||||
return success
|
return success
|
||||||
|
|
||||||
def make_reinserted_preamble(self, offset, success):
|
def make_reinserted_preamble(self, offset, success):
|
||||||
""" offset= 0 -> 1st reinserted preamble
|
""" offset= 0 -> 1st reinsesrted preamble
|
||||||
offset=-72 -> all following reinserted preambles"""
|
offset=-72 -> all following reinserted preambles"""
|
||||||
a=np.array(zip(REINSERTED_PREAMBLE[offset:],
|
a = common.make_scr(REINSERTED_PREAMBLE[offset:], REINSERTED_PREAMBLE[offset:])
|
||||||
REINSERTED_PREAMBLE[offset:]),
|
|
||||||
common.SYMB_SCRAMBLE_DTYPE)
|
|
||||||
a['symb'][-71:-71+3*13] = 0 ## D0,D1,D2
|
a['symb'][-71:-71+3*13] = 0 ## D0,D1,D2
|
||||||
print('make_reinserted_preamble', offset, success, len(a['symb']), a['symb'], a['scramble'])
|
print('make_reinserted_preamble', offset, success, len(a['symb']))
|
||||||
if not success:
|
if not success:
|
||||||
self._frame_counter = -1
|
self._frame_counter = -2
|
||||||
return a
|
return a
|
||||||
|
|
||||||
def make_data_frame(self, success):
|
def make_data_frame(self, success):
|
||||||
self._preamble_offset = -72 ## all following reinserted preambles start at index -72
|
self._preamble_offset = -72 ## all following reinserted preambles start at index -72
|
||||||
a = np.zeros(256+31, common.SYMB_SCRAMBLE_DTYPE)
|
a = np.zeros(256+31, common.SYMB_SCRAMBLE_DTYPE)
|
||||||
a['scramble'][:256] = self._data_scramble
|
a['scramble'][:256] = self._data_scramble
|
||||||
|
a['scramble_xor'][:256] = self._data_scramble_xor
|
||||||
n = (self._frame_counter-1)%72
|
n = (self._frame_counter-1)%72
|
||||||
if self._frame_counter == 72:
|
if self._frame_counter == 72:
|
||||||
self._frame_counter = -1
|
self._frame_counter = -1
|
||||||
|
@ -267,18 +356,25 @@ class PhysicalLayer(object):
|
||||||
a['symb'][256:] = MINI_PROBE[self._mp[m]]
|
a['symb'][256:] = MINI_PROBE[self._mp[m]]
|
||||||
a['scramble'][256:] = MINI_PROBE[self._mp[m]]
|
a['scramble'][256:] = MINI_PROBE[self._mp[m]]
|
||||||
if not success:
|
if not success:
|
||||||
self._frame_counter = -1
|
self._frame_counter = -2
|
||||||
return a
|
return a
|
||||||
|
|
||||||
def decode_soft_dec(self, soft_dec):
|
def decode_soft_dec(self, soft_dec):
|
||||||
return soft_dec
|
r = self._deintl_depunct.load(soft_dec)
|
||||||
|
if r.shape[0] == 0:
|
||||||
|
return []
|
||||||
|
self._viterbi_decoder.reset()
|
||||||
|
decoded_bits = self._viterbi_decoder.udpate(r)
|
||||||
|
print('bits=', decoded_bits[:100])
|
||||||
|
print('quality={}% ({},{})'.format(120.0*self._viterbi_decoder.quality()/(2*len(decoded_bits)),
|
||||||
|
self._viterbi_decoder.quality(),
|
||||||
|
len(decoded_bits)))
|
||||||
|
return decoded_bits
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_preamble():
|
def get_preamble():
|
||||||
"""preamble symbols + scrambler"""
|
"""preamble symbols + scrambler"""
|
||||||
return np.array(zip(PREAMBLE,
|
return common.make_scr(PREAMBLE, PREAMBLE)
|
||||||
PREAMBLE),
|
|
||||||
common.SYMB_SCRAMBLE_DTYPE)
|
|
||||||
|
|
||||||
def get_preamble_z(self):
|
def get_preamble_z(self):
|
||||||
"""preamble symbols for preamble correlation"""
|
"""preamble symbols for preamble correlation"""
|
||||||
|
|
|
@ -772,9 +772,14 @@ class PhysicalLayer(object):
|
||||||
else:
|
else:
|
||||||
self._state = 'MP'
|
self._state = 'MP'
|
||||||
a = np.zeros(self._unknown, common.SYMB_SCRAMBLE_DTYPE)
|
a = np.zeros(self._unknown, common.SYMB_SCRAMBLE_DTYPE)
|
||||||
|
a['scramble'][:] = 1
|
||||||
self._scr_data.reset()
|
self._scr_data.reset()
|
||||||
for i in range(self._unknown): ## TODO: handle QAM modes
|
if self._wid_mode <= MODE_8PSK: ## not QAM
|
||||||
|
for i in range(self._unknown):
|
||||||
a['scramble'][i] = np.exp(2j*np.pi*self._scr_data.next()/8)
|
a['scramble'][i] = np.exp(2j*np.pi*self._scr_data.next()/8)
|
||||||
|
else: ## QAM modes
|
||||||
|
for i in range(self._unknown):
|
||||||
|
a['scramble_xor'][i] = self._scr_data.next()
|
||||||
return self._data_mode,a
|
return self._data_mode,a
|
||||||
|
|
||||||
def get_doppler(self, iq_samples):
|
def get_doppler(self, iq_samples):
|
||||||
|
@ -869,16 +874,12 @@ class PhysicalLayer(object):
|
||||||
CNT_SCR = common.n_psk(8, np.concatenate([CNT_PN for _ in range(4)]))[:len(CNT_SYMB)]
|
CNT_SCR = common.n_psk(8, np.concatenate([CNT_PN for _ in range(4)]))[:len(CNT_SYMB)]
|
||||||
WID_SCR = common.n_psk(8, np.concatenate([WID_PN for _ in range(5)]))[:len(WID_SYMB)]
|
WID_SCR = common.n_psk(8, np.concatenate([WID_PN for _ in range(5)]))[:len(WID_SYMB)]
|
||||||
|
|
||||||
self._fixed_s = np.array(zip(SYNC_SCR*SYNC_SYMB,
|
self._fixed_s = common.make_scr(SYNC_SCR*SYNC_SYMB,
|
||||||
SYNC_SCR),
|
SYNC_SCR)
|
||||||
common.SYMB_SCRAMBLE_DTYPE)
|
self._cnt_s = common.make_scr(CNT_SCR*CNT_SYMB,
|
||||||
self._cnt_s = np.array(zip(CNT_SCR*CNT_SYMB,
|
CNT_SCR)
|
||||||
CNT_SCR),
|
self._wid_s = common.make_scr(WID_SCR*WID_SYMB,
|
||||||
common.SYMB_SCRAMBLE_DTYPE)
|
WID_SCR)
|
||||||
self._wid_s = np.array(zip(WID_SCR*WID_SYMB,
|
|
||||||
WID_SCR),
|
|
||||||
common.SYMB_SCRAMBLE_DTYPE)
|
|
||||||
|
|
||||||
|
|
||||||
def decode_soft_dec(self, soft_dec):
|
def decode_soft_dec(self, soft_dec):
|
||||||
print('decode_soft_dec', len(soft_dec), soft_dec.dtype)
|
print('decode_soft_dec', len(soft_dec), soft_dec.dtype)
|
||||||
|
|
|
@ -6,7 +6,19 @@ CONST_DTYPE=np.dtype([('points', np.complex64),
|
||||||
('symbols', np.int32)])
|
('symbols', np.int32)])
|
||||||
|
|
||||||
SYMB_SCRAMBLE_DTYPE=np.dtype([('symb', np.complex64),
|
SYMB_SCRAMBLE_DTYPE=np.dtype([('symb', np.complex64),
|
||||||
('scramble', np.complex64)])
|
('scramble', np.complex64),
|
||||||
|
('scramble_xor', np.uint8)])
|
||||||
|
|
||||||
|
def make_scr(s1, s2=None, s3=None):
|
||||||
|
a = np.zeros(len(s1), SYMB_SCRAMBLE_DTYPE)
|
||||||
|
a['symb'][:] = s1
|
||||||
|
if s2 is not None:
|
||||||
|
assert(len(s2) == len(s1))
|
||||||
|
a['scramble'][:] = s2
|
||||||
|
if s3 is not None:
|
||||||
|
assert(len(s3) == len(s1))
|
||||||
|
a['scramble_xor'][:] = s3
|
||||||
|
return a
|
||||||
|
|
||||||
def n_psk(n,x):
|
def n_psk(n,x):
|
||||||
"""n-ary PSK constellation"""
|
"""n-ary PSK constellation"""
|
||||||
|
|
|
@ -60,7 +60,7 @@ 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.5,
|
threshold = 0.3,
|
||||||
threshold_method = 1)
|
threshold_method = 1)
|
||||||
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)
|
||||||
|
|
Loading…
Reference in a new issue