From cf6113b2fe5f6f4ce683ec3037e88bb33e36cdf1 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 1 Jul 2019 20:42:53 +0200 Subject: [PATCH] Transceiver: Support TRXD v1 Related: OS#4006 Change-Id: I53db2678458a7377c87875b58b58b76a1b900517 --- Transceiver52M/Transceiver.cpp | 17 +++++++++++-- Transceiver52M/proto_trxd.c | 40 +++++++++++++++++++++++++++++++ Transceiver52M/proto_trxd.h | 44 +++++++++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 3 deletions(-) diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp index 080afd19..b73e6981 100644 --- a/Transceiver52M/Transceiver.cpp +++ b/Transceiver52M/Transceiver.cpp @@ -618,6 +618,10 @@ bool Transceiver::pullRadioVector(size_t chan, struct trx_ul_burst_ind *bi) bi->toa = 0.0; bi->noise = 0.0; bi->idle = false; + bi->modulation = MODULATION_GMSK; + bi->tss = 0; /* TODO: we only support tss 0 right now */ + bi->tsc = 0; + bi->ci = 0.0; /* Select the diversity channel with highest energy */ for (size_t i = 0; i < radio_burst->chans(); i++) { @@ -665,13 +669,18 @@ bool Transceiver::pullRadioVector(size_t chan, struct trx_ul_burst_ind *bi) type = (CorrType) rc; bi->toa = ebp.toa; + bi->tsc = ebp.tsc; + bi->ci = ebp.ci; rxBurst = demodAnyBurst(*burst, mSPSRx, ebp.amp, ebp.toa, type); /* EDGE demodulator returns 444 (gSlotLen * 3) bits */ - if (rxBurst->size() == EDGE_BURST_NBITS) + if (rxBurst->size() == EDGE_BURST_NBITS) { + bi->modulation = MODULATION_8PSK; bi->nbits = EDGE_BURST_NBITS; - else /* size() here is actually gSlotLen + 8, due to guard periods */ + } else { /* size() here is actually gSlotLen + 8, due to guard periods */ + bi->modulation = MODULATION_GMSK; bi->nbits = gSlotLen; + } // Convert -1..+1 soft bits to 0..1 soft bits vectorSlicer(bi->rx_burst, rxBurst->begin(), bi->nbits); @@ -980,6 +989,7 @@ void Transceiver::logRxBurst(size_t chan, const struct trx_ul_burst_ind *bi) << " noise: " << std::setw(5) << std::setprecision(1) << (bi->noise - rssiOffset) << "dBFS/" << std::setw(6) << -bi->noise << "dBm" << " TOA: " << std::setw(5) << std::setprecision(2) << bi->toa + << " C/I: " << std::setw(5) << std::setprecision(2) << bi->ci << "dB" << " bits: " << os; } @@ -996,6 +1006,9 @@ void Transceiver::driveReceiveFIFO(size_t chan) case 0: trxd_send_burst_ind_v0(chan, mDataSockets[chan], &bi); break; + case 1: + trxd_send_burst_ind_v1(chan, mDataSockets[chan], &bi); + break; default: OSMO_ASSERT(false); } diff --git a/Transceiver52M/proto_trxd.c b/Transceiver52M/proto_trxd.c index 5cf22e62..fff23da4 100644 --- a/Transceiver52M/proto_trxd.c +++ b/Transceiver52M/proto_trxd.c @@ -43,6 +43,21 @@ static void trxd_fill_v0_specific(struct trxd_hdr_v0_specific *v0, const struct osmo_store16be(toa_int, &v0->toa); } +static void trxd_fill_v1_specific(struct trxd_hdr_v1_specific *v1, const struct trx_ul_burst_ind *bi) +{ + int16_t ci_int_cB; + + /* deciBels->centiBels, round to closest integer */ + ci_int_cB = (int16_t)((bi->ci * 10) + 0.5); + + v1->idle = !!bi->idle; + v1->modulation = (bi->modulation == MODULATION_GMSK) ? + TRXD_MODULATION_GMSK(bi->tss) : + TRXD_MODULATION_8PSK(bi->tss); + v1->tsc = bi->tsc; + osmo_store16be(ci_int_cB, &v1->ci); +} + static void trxd_fill_burst_normalized255(uint8_t* soft_bits, const struct trx_ul_burst_ind *bi) { unsigned i; @@ -75,3 +90,28 @@ bool trxd_send_burst_ind_v0(size_t chan, int fd, const struct trx_ul_burst_ind * } return true; } + +bool trxd_send_burst_ind_v1(size_t chan, int fd, const struct trx_ul_burst_ind *bi) { + int rc; + size_t buf_len; + + buf_len = sizeof(struct trxd_hdr_v1); + if (!bi->idle) + buf_len += bi->nbits; + char buf[buf_len]; + + struct trxd_hdr_v1* pkt = (struct trxd_hdr_v1*)buf; + trxd_fill_common(&pkt->common, bi, 1); + trxd_fill_v0_specific(&pkt->v0, bi); + trxd_fill_v1_specific(&pkt->v1, bi); + + if (!bi->idle) + trxd_fill_burst_normalized255(&pkt->soft_bits[0], bi); + + rc = write(fd, buf, buf_len); + if (rc <= 0) { + CLOGCHAN(chan, DMAIN, LOGL_NOTICE, "mDataSockets write(%d) failed: %d\n", fd, rc); + return false; + } + return true; +} diff --git a/Transceiver52M/proto_trxd.h b/Transceiver52M/proto_trxd.h index 2e5ad52b..7eb5dacc 100644 --- a/Transceiver52M/proto_trxd.h +++ b/Transceiver52M/proto_trxd.h @@ -11,6 +11,16 @@ #define MAX_RX_BURST_BUF_SIZE 444 /* 444 = EDGE_BURST_NBITS */ +enum Modulation { + MODULATION_GMSK, + MODULATION_8PSK, +/* Not supported yet: + MODULATION_AQPSK, + MODULATION_16QAM, + MODULATION_32QAM +*/ +}; + struct trx_ul_burst_ind { float rx_burst[MAX_RX_BURST_BUF_SIZE]; /* soft bits normalized 0..1 */ unsigned nbits; // number of symbols per slot in rxBurst, not counting guard periods @@ -20,12 +30,17 @@ struct trx_ul_burst_ind { double toa; // in symbols double noise; // noise level in dBFS bool idle; // true if no valid burst is included + enum Modulation modulation; // modulation type + uint8_t tss; // training sequence set + uint8_t tsc; // training sequence code + float ci; // Carrier-to-Interference ratio, in dB }; bool trxd_send_burst_ind_v0(size_t chan, int fd, const struct trx_ul_burst_ind *bi); +bool trxd_send_burst_ind_v1(size_t chan, int fd, const struct trx_ul_burst_ind *bi); /* The latest supported TRXD header format version */ -#define TRX_DATA_FORMAT_VER 0 +#define TRX_DATA_FORMAT_VER 1 struct trxd_hdr_common { #if OSMO_IS_LITTLE_ENDIAN @@ -50,3 +65,30 @@ struct trxd_hdr_v0 { struct trxd_hdr_v0_specific v0; uint8_t soft_bits[0]; } __attribute__ ((packed)); + + +#define TRXD_MODULATION_GMSK(ts_set) (0b0000 | (ts_set & 0b0011)) +#define TRXD_MODULATION_8PSK(ts_set) (0b0100 | (ts_set & 0b0001)) +#define TRXD_MODULATION_AQPSK(ts_set) (0b0110 | (ts_set & 0b0001)) +#define TRXD_MODULATION_16QAM(ts_set) (0b1000 | (ts_set & 0b0001)) +#define TRXD_MODULATION_32QAM(ts_set) (0b1010 | (ts_set & 0b0001)) + +struct trxd_hdr_v1_specific { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t tsc:3, + modulation:4, + idle:1; +#elif OSMO_IS_BIG_ENDIAN + uint8_t idle:1, + modulation:4, + tsc:3; +#endif + int16_t ci; /* big endian, in centiBels */ +} __attribute__ ((packed)); + +struct trxd_hdr_v1 { + struct trxd_hdr_common common; + struct trxd_hdr_v0_specific v0; + struct trxd_hdr_v1_specific v1; + uint8_t soft_bits[0]; +} __attribute__ ((packed));