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>
This commit is contained in:
parent
5334182d5a
commit
a23f3d3243
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
|
Loading…
Reference in New Issue