diff options
author | Sylvain Munaut <tnt@246tNt.com> | 2015-04-03 20:24:10 +0200 |
---|---|---|
committer | Sylvain Munaut <tnt@246tNt.com> | 2015-04-04 13:54:30 +0200 |
commit | a23f3d3243cb99d94a3a61a8c01eb06179c2a557 (patch) | |
tree | 9a87bf3569a10b86c1852b22b8bd30a2b1be1b04 | |
parent | 5334182d5a1029a302f55273ae2a214cf3f6c38a (diff) |
sdr/pi4cxpsk: Add a method for modulation of pi/4 CxPSK bursts
This currently only supports 1sps. To upconvert, it should be
convoluted with a RRC filter.
It required adding a second table of symbol in the modulation
type where the entries are sorted by the 'bits' value rather
than the symbol number.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
-rw-r--r-- | include/osmocom/gmr1/sdr/pi4cxpsk.h | 8 | ||||
-rw-r--r-- | src/sdr/pi4cxpsk.c | 86 |
2 files changed, 90 insertions, 4 deletions
diff --git a/include/osmocom/gmr1/sdr/pi4cxpsk.h b/include/osmocom/gmr1/sdr/pi4cxpsk.h index 2247be8..1711d4d 100644 --- a/include/osmocom/gmr1/sdr/pi4cxpsk.h +++ b/include/osmocom/gmr1/sdr/pi4cxpsk.h @@ -51,7 +51,8 @@ struct gmr1_pi4cxpsk_symbol { /*! \brief pi4-CxPSK modulation description */ struct gmr1_pi4cxpsk_modulation { int nbits; /*!< \brief ebits/sym */ - struct gmr1_pi4cxpsk_symbol *syms; /*!< \brief Symbols */ + struct gmr1_pi4cxpsk_symbol *syms; /*!< \brief Symbols (sym order) */ + struct gmr1_pi4cxpsk_symbol *bits; /*!< \brief Symbols (bit order) */ }; @@ -109,6 +110,11 @@ gmr1_pi4cxpsk_detect(struct gmr1_pi4cxpsk_burst **burst_types, float e_toa, int gmr1_pi4cxpsk_mod_order(struct osmo_cxvec *burst_in, int sps, float freq_shift); +int +gmr1_pi4cxpsk_mod(struct gmr1_pi4cxpsk_burst *burst_type, + ubit_t *ebits, int sync_id, struct osmo_cxvec *burst_out); + + /*! @} */ #endif /* __OSMO_GMR1_SDR_PI4CXPSK_H__ */ diff --git a/src/sdr/pi4cxpsk.c b/src/sdr/pi4cxpsk.c index 2589fb1..d0c273b 100644 --- a/src/sdr/pi4cxpsk.c +++ b/src/sdr/pi4cxpsk.c @@ -67,7 +67,7 @@ */ /*! \brief pi4-CBPSK symbols descriptions */ -static struct gmr1_pi4cxpsk_symbol gmr1_pi4cbpsk_syms[] = { +static struct gmr1_pi4cxpsk_symbol gmr1_pi4cbpsk_syms_bits[] = { { 0, {0}, 0*M_PIf/2, 1+0*I }, { 1, {1}, 2*M_PIf/2, -1+0*I }, }; @@ -75,11 +75,12 @@ static struct gmr1_pi4cxpsk_symbol gmr1_pi4cbpsk_syms[] = { /*! \brief pi4-CBPSK modulation description */ struct gmr1_pi4cxpsk_modulation gmr1_pi4cbpsk = { .nbits = 1, - .syms = gmr1_pi4cbpsk_syms, + .syms = gmr1_pi4cbpsk_syms_bits, + .bits = gmr1_pi4cbpsk_syms_bits, }; -/*! \brief pi4-CQPSK symbols descriptions */ +/*! \brief pi4-CQPSK symbols descriptions in symbol order */ static struct gmr1_pi4cxpsk_symbol gmr1_pi4cqpsk_syms[] = { { 0, {0,0}, 0*M_PIf/2, 1+0*I }, { 1, {0,1}, 1*M_PIf/2, 0+1*I }, @@ -87,10 +88,19 @@ static struct gmr1_pi4cxpsk_symbol gmr1_pi4cqpsk_syms[] = { { 3, {1,0}, 3*M_PIf/2, 0-1*I }, }; +/*! \brief pi4-CQPSK symbols descriptions in bits order */ +static struct gmr1_pi4cxpsk_symbol gmr1_pi4cqpsk_bits[] = { + { 0, {0,0}, 0*M_PIf/2, 1+0*I }, + { 1, {0,1}, 1*M_PIf/2, 0+1*I }, + { 3, {1,0}, 3*M_PIf/2, 0-1*I }, + { 2, {1,1}, 2*M_PIf/2, -1+0*I }, +}; + /*! \brief pi4-CQPSK modulation description */ struct gmr1_pi4cxpsk_modulation gmr1_pi4cqpsk = { .nbits = 2, .syms = gmr1_pi4cqpsk_syms, + .bits = gmr1_pi4cqpsk_bits, }; @@ -704,4 +714,74 @@ err: return rv; } +/*! \brief Modulates (currently at 1 sps) + * \param[in] burst_type Burst format description + * \param[in] ebits Encoded hard bits to pack in the burst + * \param[in] sync_id The sequence id to use (0 if burst_type only has one) + * \param[out] burst_out Complex signal to fill with modulated symbols + * \returns 0 for success. -errno for errors + * + * burst_out is expected to be long enough to contains the resulting symbols + * see the burst_type structure for how long that is. + */ +int +gmr1_pi4cxpsk_mod(struct gmr1_pi4cxpsk_burst *burst_type, + ubit_t *ebits, int sync_id, struct osmo_cxvec *burst_out) +{ + struct gmr1_pi4cxpsk_modulation *mod = burst_type->mod; + struct gmr1_pi4cxpsk_sync *sync; + struct gmr1_pi4cxpsk_data *data; + int rv, i, j, k; + + /* Check the output vector is long enough */ + if (burst_out->max_len < burst_type->len) { + rv = -ENOMEM; + goto err; + } + + burst_out->len = burst_type->len; + + /* Generate reference sync bursts */ + rv = _gmr1_pi4cxpsk_sync_gen_ref(burst_type); + if (rv) + goto err; + + /* Fill guard */ + for (i=0; i<burst_type->guard_pre; i++) + burst_out->data[i] = 0.0f; + for (i=0; i<burst_type->guard_post; i++) + burst_out->data[burst_out->len - i - 1] = 0.0f; + + /* Fill training sequence */ + for (sync=burst_type->sync[sync_id]; sync->len; sync++) + { + for (i=0; i<sync->len; i++) + burst_out->data[sync->pos+i] = sync->_ref->data[i]; + } + + /* Fill ebits */ + k = 0; + + for (data=burst_type->data; data->len; data++) + { + for (i=0; i<data->len; i++) + { + int sym = 0; + + for (j=0; j<mod->nbits; j++) + sym = (sym << 1) | ebits[k++]; + + burst_out->data[data->pos+i] = burst_type->mod->bits[sym].mod_val; + } + } + + /* Apply the final pi/4 rotation */ + osmo_cxvec_rotate(burst_out, M_PIf / 4.0f, burst_out); + + rv = 0; + +err: + return rv; +} + /*! @} */ |