aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2015-04-03 20:24:10 +0200
committerSylvain Munaut <tnt@246tNt.com>2015-04-04 13:54:30 +0200
commita23f3d3243cb99d94a3a61a8c01eb06179c2a557 (patch)
tree9a87bf3569a10b86c1852b22b8bd30a2b1be1b04
parent5334182d5a1029a302f55273ae2a214cf3f6c38a (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.h8
-rw-r--r--src/sdr/pi4cxpsk.c86
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;
+}
+
/*! @} */