diff options
Diffstat (limited to 'gr-digital/lib/constellation.cc')
-rw-r--r-- | gr-digital/lib/constellation.cc | 145 |
1 files changed, 77 insertions, 68 deletions
diff --git a/gr-digital/lib/constellation.cc b/gr-digital/lib/constellation.cc index 7d2c170d34..b17635fec1 100644 --- a/gr-digital/lib/constellation.cc +++ b/gr-digital/lib/constellation.cc @@ -32,6 +32,7 @@ #include <cfloat> #include <stdexcept> #include <boost/format.hpp> +#include <iostream> namespace gr { namespace digital { @@ -129,7 +130,7 @@ namespace gr { unsigned int min_index = 0; float min_euclid_dist; float euclid_dist; - + min_euclid_dist = get_distance(0, sample); min_index = 0; for(unsigned int j = 1; j < d_arity; j++){ @@ -244,21 +245,22 @@ namespace gr { void constellation::gen_soft_dec_lut(int precision, float npwr) { - max_min_axes(); - d_lut_scale = powf(2.0, static_cast<float>(precision)); - float xstep = (d_re_max - d_re_min) / (d_lut_scale-1); - float ystep = (d_im_max - d_im_min) / (d_lut_scale-1); d_soft_dec_lut.clear(); - - float y = d_im_min; - while(y < d_im_max) { - float x = d_re_min; - while(x < d_re_max) { + d_lut_scale = powf(2.0f, static_cast<float>(precision)); + + // We know we've normalized the constellation, so the min/max + // dimensions in either direction are scaled to +/-1. + float maxd = 1.0f; + float step = (2.0f*maxd) / (d_lut_scale-1); + float y = -maxd; + while(y < maxd+step) { + float x = -maxd; + while(x < maxd+step) { gr_complex pt = gr_complex(x, y); d_soft_dec_lut.push_back(calc_soft_dec(pt, npwr)); - x += xstep; + x += step; } - y += ystep; + y += step; } d_lut_precision = precision; @@ -267,22 +269,19 @@ namespace gr { std::vector<float> constellation::calc_soft_dec(gr_complex sample, float npwr) { + int v; int M = static_cast<int>(d_constellation.size()); int k = static_cast<int>(log(static_cast<double>(M))/log(2.0)); std::vector<float> tmp(2*k, 0); std::vector<float> s(k, 0); - float scale = d_scalefactor*d_scalefactor; - int v; - for(int i = 0; i < M; i++) { // Calculate the distance between the sample and the current // constellation point. - float dist = powf(std::abs(sample - d_constellation[i]), 2.0f); - + float dist = std::abs(sample - d_constellation[i]); // Calculate the probability factor from the distance and // the scaled noise power. - float d = expf(-dist / (2.0*npwr*scale)); + float d = expf(-dist/npwr); if(d_apply_pre_diff_code) v = d_pre_diff_code[i]; @@ -307,7 +306,7 @@ namespace gr { // probability of ones (tmp[2*i+1]) over the probability of a zero // (tmp[2*i+0]). for(int i = 0; i < k; i++) { - s[k-1-i] = (logf(tmp[2*i+1]) - logf(tmp[2*i+0])) * scale; + s[k-1-i] = (logf(tmp[2*i+1]) - logf(tmp[2*i+0])); } return s; @@ -330,30 +329,40 @@ namespace gr { return d_soft_dec_lut.size() > 0; } + std::vector< std::vector<float> > + constellation::soft_dec_lut() + { + return d_soft_dec_lut; + } + std::vector<float> constellation::soft_decision_maker(gr_complex sample) { if(has_soft_dec_lut()) { - float xre = sample.real(); - float xim = sample.imag(); - - float xstep = (d_re_max-d_re_min) / d_lut_scale; - float ystep = (d_im_max-d_im_min) / d_lut_scale; - - float xscale = (d_lut_scale / (d_re_max-d_re_min)) - xstep; - float yscale = (d_lut_scale / (d_im_max-d_im_min)) - ystep; - - xre = floorf((-d_re_min + std::min(d_re_max, std::max(d_re_min, xre))) * xscale); - xim = floorf((-d_im_min + std::min(d_im_max, std::max(d_im_min, xim))) * yscale); + // Clip to just below 1 --> at 1, we can overflow the index + // that will put us in the next row of the 2D LUT. + float xre = branchless_clip(sample.real(), 0.99); + float xim = branchless_clip(sample.imag(), 0.99); + + // We normalize the constellation in the ctor, so we know that + // the maximum dimenions go from -1 to +1. We can infer the x + // and y scale directly. + float scale = d_lut_scale / (2.0f); + + // Convert the clipped x and y samples to nearest index offset + xre = floorf((1.0f + xre) * scale); + xim = floorf((1.0f + xim) * scale); int index = static_cast<int>(d_lut_scale*xim + xre); int max_index = d_lut_scale*d_lut_scale; - if(index > max_index) { - return d_soft_dec_lut[max_index-1]; - } - if(index < 0) - throw std::runtime_error("constellation::soft_decision_maker: input sample out of range."); + // Make sure we are in bounds of the index + while(index >= max_index) { + index -= d_lut_scale; + } + while(index < 0) { + index += d_lut_scale; + } return d_soft_dec_lut[index]; } @@ -412,7 +421,7 @@ namespace gr { unsigned int dimensionality) : constellation(constell, pre_diff_code, rotational_symmetry, dimensionality) {} - + // Chooses points base on shortest distance. // Inefficient. unsigned int @@ -435,11 +444,11 @@ namespace gr { n_sectors(n_sectors) { } - + constellation_sector::~constellation_sector() { } - + unsigned int constellation_sector::decision_maker(const gr_complex *sample) { @@ -447,7 +456,7 @@ namespace gr { sector = get_sector(sample); return sector_values[sector]; } - + void constellation_sector::find_sector_values() { @@ -457,11 +466,11 @@ namespace gr { sector_values.push_back(calc_sector_value(i)); } } - - + + /********************************************************************/ - - + + constellation_rect::sptr constellation_rect::make(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, @@ -495,31 +504,31 @@ namespace gr { d_width_imag_sectors *= d_scalefactor; find_sector_values(); } - + constellation_rect::~constellation_rect() { } - + unsigned int constellation_rect::get_sector(const gr_complex *sample) { int real_sector, imag_sector; unsigned int sector; - + real_sector = int(real(*sample)/d_width_real_sectors + n_real_sectors/2.0); if(real_sector < 0) real_sector = 0; if(real_sector >= (int)n_real_sectors) real_sector = n_real_sectors-1; - + imag_sector = int(imag(*sample)/d_width_imag_sectors + n_imag_sectors/2.0); if(imag_sector < 0) imag_sector = 0; if(imag_sector >= (int)n_imag_sectors) imag_sector = n_imag_sectors-1; - + sector = real_sector * n_imag_sectors + imag_sector; return sector; } @@ -536,7 +545,7 @@ namespace gr { (imag_sector + 0.5 - n_imag_sectors/2.0) * d_width_imag_sectors); return sector_center; } - + unsigned int constellation_rect::calc_sector_value(unsigned int sector) { @@ -547,8 +556,8 @@ namespace gr { } /********************************************************************/ - - constellation_expl_rect::sptr + + constellation_expl_rect::sptr constellation_expl_rect::make(std::vector<gr_complex> constellation, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, @@ -565,7 +574,7 @@ namespace gr { width_real_sectors, width_imag_sectors, sector_values)); } - + constellation_expl_rect::constellation_expl_rect( std::vector<gr_complex> constellation, std::vector<int> pre_diff_code, @@ -580,16 +589,16 @@ namespace gr { d_sector_values(sector_values) { } - + constellation_expl_rect::~constellation_expl_rect() { } - + /********************************************************************/ - - - constellation_psk::sptr - constellation_psk::make(std::vector<gr_complex> constell, + + + constellation_psk::sptr + constellation_psk::make(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int n_sectors) { @@ -597,7 +606,7 @@ namespace gr { (constell, pre_diff_code, n_sectors)); } - + constellation_psk::constellation_psk(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int n_sectors) : @@ -606,11 +615,11 @@ namespace gr { { find_sector_values(); } - + constellation_psk::~constellation_psk() { } - + unsigned int constellation_psk::get_sector(const gr_complex *sample) { @@ -621,7 +630,7 @@ namespace gr { sector += n_sectors; return sector; } - + unsigned int constellation_psk::calc_sector_value(unsigned int sector) { @@ -635,7 +644,7 @@ namespace gr { /********************************************************************/ - constellation_bpsk::sptr + constellation_bpsk::sptr constellation_bpsk::make() { return constellation_bpsk::sptr(new constellation_bpsk()); @@ -665,7 +674,7 @@ namespace gr { /********************************************************************/ - constellation_qpsk::sptr + constellation_qpsk::sptr constellation_qpsk::make() { return constellation_qpsk::sptr(new constellation_qpsk()); @@ -679,7 +688,7 @@ namespace gr { d_constellation[1] = gr_complex(SQRT_TWO, -SQRT_TWO); d_constellation[2] = gr_complex(-SQRT_TWO, SQRT_TWO); d_constellation[3] = gr_complex(SQRT_TWO, SQRT_TWO); - + /* d_constellation[0] = gr_complex(SQRT_TWO, SQRT_TWO); d_constellation[1] = gr_complex(-SQRT_TWO, SQRT_TWO); @@ -701,7 +710,7 @@ namespace gr { constellation_qpsk::~constellation_qpsk() { } - + unsigned int constellation_qpsk::decision_maker(const gr_complex *sample) { @@ -731,7 +740,7 @@ namespace gr { /********************************************************************/ - constellation_dqpsk::sptr + constellation_dqpsk::sptr constellation_dqpsk::make() { return constellation_dqpsk::sptr(new constellation_dqpsk()); @@ -791,7 +800,7 @@ namespace gr { /********************************************************************/ - constellation_8psk::sptr + constellation_8psk::sptr constellation_8psk::make() { return constellation_8psk::sptr(new constellation_8psk()); |