trcon<->l1 data if without sockets
direct call of UL rx receive data handler + sched check if ts is active tx dir call stub for for tx thread queue. Change-Id: I5911004db58742cf39b968fcf87bc1243f7a374a
This commit is contained in:
parent
70bd9415a2
commit
2ecd9f698f
|
@ -191,7 +191,6 @@ noinst_HEADERS += \
|
||||||
ms/bladerf_specific.h \
|
ms/bladerf_specific.h \
|
||||||
ms/uhd_specific.h \
|
ms/uhd_specific.h \
|
||||||
ms/ms_rx_upper.h \
|
ms/ms_rx_upper.h \
|
||||||
ms/ms_state.h \
|
|
||||||
itrq.h
|
itrq.h
|
||||||
# -fsanitize=address,undefined -shared-libsan -O0
|
# -fsanitize=address,undefined -shared-libsan -O0
|
||||||
#
|
#
|
||||||
|
|
|
@ -20,10 +20,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <radioInterface.h>
|
#include <radioInterface.h>
|
||||||
#include "l1if.h"
|
|
||||||
#include "ms_rx_upper.h"
|
#include "ms_rx_upper.h"
|
||||||
#include "syncthing.h"
|
#include "syncthing.h"
|
||||||
#include "ms_state.h"
|
|
||||||
|
|
||||||
void upper_trx::driveControl()
|
void upper_trx::driveControl()
|
||||||
{
|
{
|
||||||
|
@ -199,8 +197,6 @@ void upper_trx::commandhandler(char *buffer, char *response)
|
||||||
sprintf(response, "RSP SETSLOT 1 %d %d", timeslot, corrCode);
|
sprintf(response, "RSP SETSLOT 1 %d %d", timeslot, corrCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mStates.chanType[timeslot] = (ChannelCombination)corrCode;
|
|
||||||
mStates.setModulus(timeslot);
|
|
||||||
sprintf(response, "RSP SETSLOT 0 %d %d", timeslot, corrCode);
|
sprintf(response, "RSP SETSLOT 0 %d %d", timeslot, corrCode);
|
||||||
} else if (!strcmp(command, "SETRXMASK")) {
|
} else if (!strcmp(command, "SETRXMASK")) {
|
||||||
int slot;
|
int slot;
|
||||||
|
@ -214,7 +210,6 @@ void upper_trx::commandhandler(char *buffer, char *response)
|
||||||
}
|
}
|
||||||
} else if (!strcmp(command, "SYNC")) {
|
} else if (!strcmp(command, "SYNC")) {
|
||||||
// msleep(10);
|
// msleep(10);
|
||||||
mStates.mode = trx_mode::TRX_MODE_MS_TRACK;
|
|
||||||
sprintf(response, "RSP SYNC 0");
|
sprintf(response, "RSP SYNC 0");
|
||||||
mMaxExpectedDelay = 48;
|
mMaxExpectedDelay = 48;
|
||||||
// setRxGain(30);
|
// setRxGain(30);
|
||||||
|
|
|
@ -21,12 +21,10 @@
|
||||||
|
|
||||||
#include "sigProcLib.h"
|
#include "sigProcLib.h"
|
||||||
#include "syncthing.h"
|
#include "syncthing.h"
|
||||||
#include "l1if.h"
|
|
||||||
#include <signalVector.h>
|
#include <signalVector.h>
|
||||||
#include <radioVector.h>
|
#include <radioVector.h>
|
||||||
#include <radioInterface.h>
|
#include <radioInterface.h>
|
||||||
#include "grgsm_vitac/grgsm_vitac.h"
|
#include "grgsm_vitac/grgsm_vitac.h"
|
||||||
#include "ms_state.h"
|
|
||||||
#include "ms_rx_upper.h"
|
#include "ms_rx_upper.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -39,6 +37,15 @@ extern "C" {
|
||||||
void __lsan_do_recoverable_leak_check();
|
void __lsan_do_recoverable_leak_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace trxcon
|
||||||
|
{
|
||||||
|
extern "C" {
|
||||||
|
#include <trxcon/trx_if.h>
|
||||||
|
}
|
||||||
|
trx_instance *trxcon_instance; // local handle
|
||||||
|
static tx_queue_t txq;
|
||||||
|
} // namespace trxcon
|
||||||
|
|
||||||
#ifdef LOG
|
#ifdef LOG
|
||||||
#undef LOG
|
#undef LOG
|
||||||
#define LOG(...) upper_trx::dummy_log()
|
#define LOG(...) upper_trx::dummy_log()
|
||||||
|
@ -89,35 +96,6 @@ void upper_trx::start_ms()
|
||||||
ms_trx::start();
|
ms_trx::start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detect SCH synchronization sequence within a burst */
|
|
||||||
bool upper_trx::detectSCH(ms_TransceiverState *state, signalVector &burst, struct estim_burst_params *ebp)
|
|
||||||
{
|
|
||||||
int shift;
|
|
||||||
sch_detect_type full;
|
|
||||||
float mag, threshold = 4.0;
|
|
||||||
|
|
||||||
full = (state->mode == trx_mode::TRX_MODE_MS_TRACK) ? sch_detect_type::SCH_DETECT_NARROW :
|
|
||||||
sch_detect_type::SCH_DETECT_FULL;
|
|
||||||
|
|
||||||
if (!detectSCHBurst(burst, threshold, rx_sps, full, ebp))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::clog << "SCH : Timing offset " << ebp->toa << " symbols" << std::endl;
|
|
||||||
|
|
||||||
mag = fabsf(ebp->toa);
|
|
||||||
if (mag < 1.0f)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
shift = (int)(mag / 2.0f);
|
|
||||||
if (!shift)
|
|
||||||
shift++;
|
|
||||||
|
|
||||||
shift = ebp->toa > 0 ? shift : -shift;
|
|
||||||
std::clog << "SCH : shift -> " << shift << " symbols" << std::endl;
|
|
||||||
// mRadioInterface->applyOffset(shift);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SoftVector *upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset) __attribute__((optnone))
|
SoftVector *upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset) __attribute__((optnone))
|
||||||
{
|
{
|
||||||
float pow, avg = 1.0;
|
float pow, avg = 1.0;
|
||||||
|
@ -161,50 +139,20 @@ SoftVector *upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingO
|
||||||
return &bits;
|
return &bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
CorrType type = TSC;
|
auto ts = trxcon::trxcon_instance->ts_list[burst_time.TN()];
|
||||||
|
if (ts == NULL || ts->mf_layout == NULL)
|
||||||
// tickle UL by returning null bursts if demod is skipped due to unused TS
|
return 0;
|
||||||
switch (mStates.mode) {
|
|
||||||
case trx_mode::TRX_MODE_MS_TRACK:
|
|
||||||
if (mStates.chanType[burst_time.TN()] == ChannelCombination::NONE_INACTIVE) {
|
|
||||||
type = OFF;
|
|
||||||
goto release;
|
|
||||||
} else if (is_sch)
|
|
||||||
type = SCH;
|
|
||||||
else if (!is_fcch) // all ts0, but not fcch or sch..
|
|
||||||
type = TSC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case trx_mode::TRX_MODE_OFF:
|
|
||||||
default:
|
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
|
|
||||||
convert_and_scale<float, int16_t>(ss, e.burst, ONE_TS_BURST_LEN * 2, 1.f / float(rxFullScale));
|
convert_and_scale<float, int16_t>(ss, e.burst, ONE_TS_BURST_LEN * 2, 1.f / float(rxFullScale));
|
||||||
|
|
||||||
pow = energyDetect(sv, 20 * rx_sps);
|
pow = energyDetect(sv, 20 * rx_sps);
|
||||||
if (pow < -1) {
|
if (pow < -1) {
|
||||||
LOG(ALERT) << "Received empty burst";
|
LOG(ALERT) << "Received empty burst";
|
||||||
goto release;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
avg = sqrt(pow);
|
avg = sqrt(pow);
|
||||||
|
{
|
||||||
if (type == SCH) {
|
|
||||||
std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
|
|
||||||
int d_c0_burst_start = get_sch_chan_imp_resp(ss, &chan_imp_resp[0]);
|
|
||||||
detect_burst(ss, &chan_imp_resp[0], d_c0_burst_start, outbin);
|
|
||||||
|
|
||||||
for (int i = 0; i < 148; i++)
|
|
||||||
(bits)[i] = (!outbin[i]) < 1 ? -1 : 1;
|
|
||||||
|
|
||||||
// auto rv = decode_sch(bits->begin(), false);
|
|
||||||
// dbgout << "U SCH@"
|
|
||||||
// << " " << e.gsmts.FN() << ":" << e.gsmts.TN() << " " << d_c0_burst_start
|
|
||||||
// << " DECODE:" << (rv ? "yes" : "---") << std::endl;
|
|
||||||
|
|
||||||
// std::cerr << dbgout.str();
|
|
||||||
} else {
|
|
||||||
float ncmax, dcmax;
|
float ncmax, dcmax;
|
||||||
std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
|
std::complex<float> chan_imp_resp[CHAN_IMP_RESP_LENGTH * d_OSR];
|
||||||
std::complex<float> chan_imp_resp2[CHAN_IMP_RESP_LENGTH * d_OSR];
|
std::complex<float> chan_imp_resp2[CHAN_IMP_RESP_LENGTH * d_OSR];
|
||||||
|
@ -227,14 +175,10 @@ SoftVector *upper_trx::pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingO
|
||||||
for (int i = 0; i < 148; i++)
|
for (int i = 0; i < 148; i++)
|
||||||
(bits)[i] = (outbin[i]) < 1 ? -1 : 1;
|
(bits)[i] = (outbin[i]) < 1 ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RSSI = (int)floor(20.0 * log10(rxFullScale / avg));
|
RSSI = (int)floor(20.0 * log10(rxFullScale / avg));
|
||||||
timingOffset = (int)round(0);
|
timingOffset = (int)round(0);
|
||||||
|
|
||||||
return &bits;
|
return &bits;
|
||||||
|
|
||||||
release:
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void upper_trx::driveReceiveFIFO()
|
void upper_trx::driveReceiveFIFO()
|
||||||
|
@ -248,12 +192,13 @@ void upper_trx::driveReceiveFIFO()
|
||||||
|
|
||||||
SoftVector *rxBurst = pullRadioVector(burstTime, RSSI, TOA);
|
SoftVector *rxBurst = pullRadioVector(burstTime, RSSI, TOA);
|
||||||
|
|
||||||
trxd_from_trx response;
|
|
||||||
response.ts = burstTime.TN();
|
|
||||||
response.fn = htonl(burstTime.FN());
|
|
||||||
response.rssi = RSSI;
|
|
||||||
response.toa = htons(TOA);
|
|
||||||
if (rxBurst) {
|
if (rxBurst) {
|
||||||
|
trxd_from_trx response;
|
||||||
|
response.ts = burstTime.TN();
|
||||||
|
response.fn = htonl(burstTime.FN());
|
||||||
|
response.rssi = RSSI;
|
||||||
|
response.toa = htons(TOA);
|
||||||
|
|
||||||
SoftVector::const_iterator burstItr = rxBurst->begin();
|
SoftVector::const_iterator burstItr = rxBurst->begin();
|
||||||
if (burstTime.TN() == 0 && gsm_sch_check_fn(burstTime.FN())) {
|
if (burstTime.TN() == 0 && gsm_sch_check_fn(burstTime.FN())) {
|
||||||
clamp_array(rxBurst->begin(), 148, 1.5f);
|
clamp_array(rxBurst->begin(), 148, 1.5f);
|
||||||
|
@ -267,45 +212,19 @@ void upper_trx::driveReceiveFIFO()
|
||||||
for (int i = 0; i < 148; i++)
|
for (int i = 0; i < 148; i++)
|
||||||
((int8_t *)response.symbols)[i] = *burstItr++ > 0.0f ? -127 : 127;
|
((int8_t *)response.symbols)[i] = *burstItr++ > 0.0f ? -127 : 127;
|
||||||
}
|
}
|
||||||
|
trxcon::trx_data_rx_handler(trxcon::trxcon_instance, (uint8_t *)&response);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IPCIF
|
|
||||||
push_d(response);
|
|
||||||
#else
|
|
||||||
int rv = sendto(mDataSockets, &response, sizeof(trxd_from_trx), 0, (struct sockaddr *)&datadest,
|
|
||||||
sizeof(struct sockaddr_in));
|
|
||||||
if (rv < 0) {
|
|
||||||
std::cerr << "fuck, send?" << std::endl;
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void upper_trx::driveTx()
|
void upper_trx::driveTx()
|
||||||
{
|
{
|
||||||
#ifdef IPCIF
|
trxd_to_trx e;
|
||||||
auto burst = pop_d();
|
while (!trxcon::txq.spsc_pop(&e)) {
|
||||||
if (!burst) {
|
trxcon::txq.spsc_prep_pop();
|
||||||
// std::cerr << "wtf no tx burst?" << std::endl;
|
|
||||||
// exit(0);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
trxd_to_trx buffer;
|
|
||||||
|
|
||||||
socklen_t addr_len = sizeof(datasrc);
|
trxd_to_trx *burst = &e;
|
||||||
int rdln = recvfrom(mDataSockets, (void *)&buffer, sizeof(trxd_to_trx), 0, &datasrc, &addr_len);
|
|
||||||
if (rdln < 0 && errno == EAGAIN) {
|
|
||||||
std::cerr << "fuck, rcv?" << std::endl;
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
if(rdln < sizeof(buffer)) // nope ind has len 6 or something like that
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
trxd_to_trx *burst = &buffer;
|
|
||||||
#endif
|
|
||||||
auto proper_fn = ntohl(burst->fn);
|
auto proper_fn = ntohl(burst->fn);
|
||||||
// std::cerr << "got burst!" << proper_fn << ":" << burst->ts
|
// std::cerr << "got burst!" << proper_fn << ":" << burst->ts
|
||||||
// << " current: " << timekeeper.gsmtime().FN()
|
// << " current: " << timekeeper.gsmtime().FN()
|
||||||
|
@ -341,30 +260,8 @@ void upper_trx::driveTx()
|
||||||
|
|
||||||
submit_burst(burst_buf, txburst->size(), currTime);
|
submit_burst(burst_buf, txburst->size(), currTime);
|
||||||
delete txburst;
|
delete txburst;
|
||||||
|
|
||||||
#ifdef IPCIF
|
|
||||||
free(burst);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// __attribute__((xray_always_instrument)) static void *rx_stream_callback(struct bladerf *dev,
|
|
||||||
// struct bladerf_stream *stream,
|
|
||||||
// struct bladerf_metadata *meta, void *samples,
|
|
||||||
// size_t num_samples, void *user_data)
|
|
||||||
// {
|
|
||||||
// struct ms_trx *trx = (struct ms_trx *)user_data;
|
|
||||||
// return trx->rx_cb(dev, stream, meta, samples, num_samples, user_data);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// __attribute__((xray_always_instrument)) static void *tx_stream_callback(struct bladerf *dev,
|
|
||||||
// struct bladerf_stream *stream,
|
|
||||||
// struct bladerf_metadata *meta, void *samples,
|
|
||||||
// size_t num_samples, void *user_data)
|
|
||||||
// {
|
|
||||||
// struct ms_trx *trx = (struct ms_trx *)user_data;
|
|
||||||
// return BLADERF_STREAM_NO_DATA;
|
|
||||||
// }
|
|
||||||
|
|
||||||
int trxc_main(int argc, char *argv[])
|
int trxc_main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
pthread_setname_np(pthread_self(), "main_trxc");
|
pthread_setname_np(pthread_self(), "main_trxc");
|
||||||
|
@ -384,14 +281,21 @@ int trxc_main(int argc, char *argv[])
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" volatile bool gshutdown = false;
|
extern "C" {
|
||||||
extern "C" void init_external_transceiver(int argc, char **argv)
|
void init_external_transceiver(struct trx_instance *trx, int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
trxcon::trxcon_instance = (trxcon::trx_instance *)trx;
|
||||||
std::cout << "init?" << std::endl;
|
std::cout << "init?" << std::endl;
|
||||||
trxc_main(argc, argv);
|
trxc_main(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void stop_trx()
|
void close_external_transceiver(int argc, char **argv)
|
||||||
{
|
{
|
||||||
std::cout << "Shutting down transceiver..." << std::endl;
|
std::cout << "Shutting down transceiver..." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tx_external_transceiver(uint8_t *burst)
|
||||||
|
{
|
||||||
|
trxcon::txq.spsc_push((trxd_to_trx *)burst);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,13 +28,12 @@
|
||||||
#include "GSMCommon.h"
|
#include "GSMCommon.h"
|
||||||
#include "radioClock.h"
|
#include "radioClock.h"
|
||||||
#include "syncthing.h"
|
#include "syncthing.h"
|
||||||
#include "ms_state.h"
|
#include "l1if.h"
|
||||||
|
|
||||||
|
using tx_queue_t = spsc_cond<8 * 1, trxd_to_trx, true, false>;
|
||||||
class upper_trx : public ms_trx {
|
class upper_trx : public ms_trx {
|
||||||
int rx_sps, tx_sps;
|
int rx_sps, tx_sps;
|
||||||
|
|
||||||
ms_TransceiverState mStates;
|
|
||||||
|
|
||||||
bool mOn; ///< flag to indicate that transceiver is powered on
|
bool mOn; ///< flag to indicate that transceiver is powered on
|
||||||
double mTxFreq; ///< the transmit frequency
|
double mTxFreq; ///< the transmit frequency
|
||||||
double mRxFreq; ///< the receive frequency
|
double mRxFreq; ///< the receive frequency
|
||||||
|
@ -42,9 +41,6 @@ class upper_trx : public ms_trx {
|
||||||
unsigned mMaxExpectedDelay; ///< maximum TOA offset in GSM symbols
|
unsigned mMaxExpectedDelay; ///< maximum TOA offset in GSM symbols
|
||||||
unsigned long long mRxSlotMask[8]; ///< MS - enabled multiframe slot mask
|
unsigned long long mRxSlotMask[8]; ///< MS - enabled multiframe slot mask
|
||||||
|
|
||||||
int mDataSockets;
|
|
||||||
sockaddr_in datadest;
|
|
||||||
sockaddr datasrc;
|
|
||||||
int mCtrlSockets;
|
int mCtrlSockets;
|
||||||
sockaddr_in ctrldest;
|
sockaddr_in ctrldest;
|
||||||
sockaddr ctrlsrc;
|
sockaddr ctrlsrc;
|
||||||
|
@ -98,8 +94,6 @@ class upper_trx : public ms_trx {
|
||||||
|
|
||||||
SoftVector *pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset);
|
SoftVector *pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset);
|
||||||
|
|
||||||
bool detectSCH(ms_TransceiverState *state, signalVector &burst, struct estim_burst_params *ebp);
|
|
||||||
|
|
||||||
std::thread thr_control, thr_rx, thr_tx;
|
std::thread thr_control, thr_rx, thr_tx;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -110,12 +104,8 @@ class upper_trx : public ms_trx {
|
||||||
{
|
{
|
||||||
auto c_srcport = 6700 + 2 * 0 + 1;
|
auto c_srcport = 6700 + 2 * 0 + 1;
|
||||||
auto c_dstport = 6700 + 2 * 0 + 101;
|
auto c_dstport = 6700 + 2 * 0 + 101;
|
||||||
auto d_srcport = 6700 + 2 * 0 + 2;
|
|
||||||
auto d_dstport = 6700 + 2 * 0 + 102;
|
|
||||||
|
|
||||||
openudp(&mCtrlSockets, c_srcport, "127.0.0.1");
|
openudp(&mCtrlSockets, c_srcport, "127.0.0.1");
|
||||||
openudp(&mDataSockets, d_srcport, "127.0.0.1");
|
|
||||||
resolveAddress(&ctrldest, "127.0.0.1", c_dstport);
|
resolveAddress(&ctrldest, "127.0.0.1", c_dstport);
|
||||||
resolveAddress(&datadest, "127.0.0.1", d_dstport);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,175 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <radioVector.h>
|
|
||||||
#include <signalVector.h>
|
|
||||||
|
|
||||||
enum class trx_mode {
|
|
||||||
TRX_MODE_OFF,
|
|
||||||
TRX_MODE_BTS,
|
|
||||||
TRX_MODE_MS_ACQUIRE,
|
|
||||||
TRX_MODE_MS_TRACK,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ChannelCombination {
|
|
||||||
FILL, ///< Channel is transmitted, but unused
|
|
||||||
I, ///< TCH/FS
|
|
||||||
II, ///< TCH/HS, idle every other slot
|
|
||||||
III, ///< TCH/HS
|
|
||||||
IV, ///< FCCH+SCH+CCCH+BCCH, uplink RACH
|
|
||||||
V, ///< FCCH+SCH+CCCH+BCCH+SDCCH/4+SACCH/4, uplink RACH+SDCCH/4
|
|
||||||
VI, ///< CCCH+BCCH, uplink RACH
|
|
||||||
VII, ///< SDCCH/8 + SACCH/8
|
|
||||||
VIII, ///< TCH/F + FACCH/F + SACCH/M
|
|
||||||
IX, ///< TCH/F + SACCH/M
|
|
||||||
X, ///< TCH/FD + SACCH/MD
|
|
||||||
XI, ///< PBCCH+PCCCH+PDTCH+PACCH+PTCCH
|
|
||||||
XII, ///< PCCCH+PDTCH+PACCH+PTCCH
|
|
||||||
XIII, ///< PDTCH+PACCH+PTCCH
|
|
||||||
NONE_INACTIVE, ///< Channel is inactive, default
|
|
||||||
LOOPBACK ///< similar go VII, used in loopback testing
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ms_TransceiverState {
|
|
||||||
ms_TransceiverState() : mFreqOffsets(10), mode(trx_mode::TRX_MODE_OFF)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
chanType[i] = ChannelCombination::NONE_INACTIVE;
|
|
||||||
fillerModulus[i] = 26;
|
|
||||||
|
|
||||||
for (int n = 0; n < 102; n++)
|
|
||||||
fillerTable[n][i] = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~ms_TransceiverState()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
for (int n = 0; n < 102; n++)
|
|
||||||
delete fillerTable[n][i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setModulus(size_t timeslot)
|
|
||||||
{
|
|
||||||
switch (chanType[timeslot]) {
|
|
||||||
case ChannelCombination::NONE_INACTIVE:
|
|
||||||
case ChannelCombination::I:
|
|
||||||
case ChannelCombination::II:
|
|
||||||
case ChannelCombination::III:
|
|
||||||
case ChannelCombination::FILL:
|
|
||||||
fillerModulus[timeslot] = 26;
|
|
||||||
break;
|
|
||||||
case ChannelCombination::IV:
|
|
||||||
case ChannelCombination::VI:
|
|
||||||
case ChannelCombination::V:
|
|
||||||
fillerModulus[timeslot] = 51;
|
|
||||||
break;
|
|
||||||
//case V:
|
|
||||||
case ChannelCombination::VII:
|
|
||||||
fillerModulus[timeslot] = 102;
|
|
||||||
break;
|
|
||||||
case ChannelCombination::XIII:
|
|
||||||
fillerModulus[timeslot] = 52;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CorrType expectedCorrType(GSM::Time currTime, unsigned long long *mRxSlotMask)
|
|
||||||
{
|
|
||||||
unsigned burstTN = currTime.TN();
|
|
||||||
unsigned burstFN = currTime.FN();
|
|
||||||
|
|
||||||
if (mode == trx_mode::TRX_MODE_MS_TRACK) {
|
|
||||||
/* 102 modulus case currently unhandled */
|
|
||||||
if (fillerModulus[burstTN] > 52)
|
|
||||||
return OFF;
|
|
||||||
|
|
||||||
int modFN = burstFN % fillerModulus[burstTN];
|
|
||||||
unsigned long long reg = (unsigned long long)1 << modFN;
|
|
||||||
if (reg & mRxSlotMask[burstTN])
|
|
||||||
return TSC;
|
|
||||||
else
|
|
||||||
return OFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (chanType[burstTN]) {
|
|
||||||
case ChannelCombination::NONE_INACTIVE:
|
|
||||||
return OFF;
|
|
||||||
break;
|
|
||||||
case ChannelCombination::FILL:
|
|
||||||
return IDLE;
|
|
||||||
break;
|
|
||||||
case ChannelCombination::I:
|
|
||||||
return TSC;
|
|
||||||
/*if (burstFN % 26 == 25)
|
|
||||||
return IDLE;
|
|
||||||
else
|
|
||||||
return TSC;*/
|
|
||||||
break;
|
|
||||||
case ChannelCombination::II:
|
|
||||||
return TSC;
|
|
||||||
break;
|
|
||||||
case ChannelCombination::III:
|
|
||||||
return TSC;
|
|
||||||
break;
|
|
||||||
case ChannelCombination::IV:
|
|
||||||
case ChannelCombination::VI:
|
|
||||||
return RACH;
|
|
||||||
break;
|
|
||||||
case ChannelCombination::V: {
|
|
||||||
int mod51 = burstFN % 51;
|
|
||||||
if ((mod51 <= 36) && (mod51 >= 14))
|
|
||||||
return RACH;
|
|
||||||
else if ((mod51 == 4) || (mod51 == 5))
|
|
||||||
return RACH;
|
|
||||||
else if ((mod51 == 45) || (mod51 == 46))
|
|
||||||
return RACH;
|
|
||||||
else
|
|
||||||
return TSC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ChannelCombination::VII:
|
|
||||||
if ((burstFN % 51 <= 14) && (burstFN % 51 >= 12))
|
|
||||||
return IDLE;
|
|
||||||
else
|
|
||||||
return TSC;
|
|
||||||
break;
|
|
||||||
case ChannelCombination::XIII: {
|
|
||||||
int mod52 = burstFN % 52;
|
|
||||||
if ((mod52 == 12) || (mod52 == 38))
|
|
||||||
return RACH;
|
|
||||||
else if ((mod52 == 25) || (mod52 == 51))
|
|
||||||
return IDLE;
|
|
||||||
else
|
|
||||||
return TSC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ChannelCombination::LOOPBACK:
|
|
||||||
if ((burstFN % 51 <= 50) && (burstFN % 51 >= 48))
|
|
||||||
return IDLE;
|
|
||||||
else
|
|
||||||
return TSC;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return OFF;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize a multiframe slot in the filler table */
|
|
||||||
void init(size_t slot, signalVector *burst, bool fill);
|
|
||||||
|
|
||||||
ChannelCombination chanType[8];
|
|
||||||
|
|
||||||
/* The filler table */
|
|
||||||
signalVector *fillerTable[102][8];
|
|
||||||
int fillerModulus[8];
|
|
||||||
|
|
||||||
/* Received noise energy levels */
|
|
||||||
avgVector mFreqOffsets;
|
|
||||||
|
|
||||||
/* Transceiver mode */
|
|
||||||
trx_mode mode;
|
|
||||||
};
|
|
|
@ -602,32 +602,9 @@ rsp_error:
|
||||||
static int trx_data_rx_cb(struct osmo_fd *ofd, unsigned int what)
|
static int trx_data_rx_cb(struct osmo_fd *ofd, unsigned int what)
|
||||||
{
|
{
|
||||||
struct trx_instance *trx = ofd->data;
|
struct trx_instance *trx = ofd->data;
|
||||||
struct trx_meas_set meas;
|
|
||||||
uint8_t buf[TRXD_BUF_SIZE];
|
uint8_t buf[TRXD_BUF_SIZE];
|
||||||
sbit_t bits[148];
|
|
||||||
int8_t rssi, tn;
|
|
||||||
int16_t toa256;
|
|
||||||
uint32_t fn;
|
|
||||||
ssize_t read_len;
|
ssize_t read_len;
|
||||||
|
|
||||||
#ifdef IPCIF
|
|
||||||
struct trxd_from_trx* rcvd = trxif_from_trx_d();
|
|
||||||
if (!rcvd) {
|
|
||||||
LOGP(DTRX, LOGL_ERROR, "read() failed with rc=%zd\n", rcvd);
|
|
||||||
return rcvd;
|
|
||||||
}
|
|
||||||
|
|
||||||
tn = rcvd->ts;
|
|
||||||
fn = rcvd->fn;
|
|
||||||
rssi = -(int8_t) rcvd->rssi;
|
|
||||||
toa256 = (int16_t) rcvd->toa;
|
|
||||||
|
|
||||||
/* Copy and convert bits {254..0} to sbits {-127..127} */
|
|
||||||
//osmo_ubit2sbit(bits, rcvd->symbols, 148);
|
|
||||||
memcpy(bits, rcvd->symbols, 148);
|
|
||||||
|
|
||||||
free(rcvd);
|
|
||||||
#else
|
|
||||||
read_len = read(ofd->fd, buf, sizeof(buf));
|
read_len = read(ofd->fd, buf, sizeof(buf));
|
||||||
if (read_len <= 0) {
|
if (read_len <= 0) {
|
||||||
LOGP(DTRXD, LOGL_ERROR, "read() failed with rc=%zd\n", read_len);
|
LOGP(DTRXD, LOGL_ERROR, "read() failed with rc=%zd\n", read_len);
|
||||||
|
@ -641,7 +618,18 @@ static int trx_data_rx_cb(struct osmo_fd *ofd, unsigned int what)
|
||||||
read_len);
|
read_len);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
return trx_data_rx_handler(trx, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int trx_data_rx_handler(struct trx_instance *trx, uint8_t *buf)
|
||||||
|
{
|
||||||
|
struct trx_meas_set meas;
|
||||||
|
sbit_t bits[148];
|
||||||
|
int8_t rssi, tn;
|
||||||
|
int16_t toa256;
|
||||||
|
uint32_t fn;
|
||||||
|
|
||||||
tn = buf[0];
|
tn = buf[0];
|
||||||
fn = osmo_load32be(buf + 1);
|
fn = osmo_load32be(buf + 1);
|
||||||
rssi = -(int8_t)buf[5];
|
rssi = -(int8_t)buf[5];
|
||||||
|
@ -681,6 +669,8 @@ static int trx_data_rx_cb(struct osmo_fd *ofd, unsigned int what)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void tx_external_transceiver(uint8_t *burst) __attribute__((weak));
|
||||||
|
|
||||||
int trx_if_tx_burst(struct trx_instance *trx, uint8_t tn, uint32_t fn,
|
int trx_if_tx_burst(struct trx_instance *trx, uint8_t tn, uint32_t fn,
|
||||||
uint8_t pwr, const ubit_t *bits)
|
uint8_t pwr, const ubit_t *bits)
|
||||||
{
|
{
|
||||||
|
@ -719,7 +709,10 @@ int trx_if_tx_burst(struct trx_instance *trx, uint8_t tn, uint32_t fn,
|
||||||
memcpy(buf + 6, bits, 148);
|
memcpy(buf + 6, bits, 148);
|
||||||
|
|
||||||
/* Send data to transceiver */
|
/* Send data to transceiver */
|
||||||
send(trx->trx_ofd_data.fd, buf, 154, 0);
|
if (tx_external_transceiver)
|
||||||
|
tx_external_transceiver(buf);
|
||||||
|
else
|
||||||
|
send(trx->trx_ofd_data.fd, buf, 154, 0);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -84,3 +84,4 @@ int trx_if_cmd_measure(struct trx_instance *trx,
|
||||||
|
|
||||||
int trx_if_tx_burst(struct trx_instance *trx, uint8_t tn, uint32_t fn,
|
int trx_if_tx_burst(struct trx_instance *trx, uint8_t tn, uint32_t fn,
|
||||||
uint8_t pwr, const ubit_t *bits);
|
uint8_t pwr, const ubit_t *bits);
|
||||||
|
int trx_data_rx_handler(struct trx_instance *trx, uint8_t *buf);
|
|
@ -271,9 +271,8 @@ static void signal_handler(int signum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void init_external_transceiver(int argc, char **argv);
|
extern void init_external_transceiver(struct trx_instance *trx, int argc, char **argv) __attribute__((weak));
|
||||||
extern void stop_trx();
|
extern void close_external_transceiver(int argc, char **argv) __attribute__((weak));
|
||||||
extern volatile bool gshutdown;
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -372,14 +371,14 @@ int main(int argc, char **argv)
|
||||||
/* Initialize pseudo-random generator */
|
/* Initialize pseudo-random generator */
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
init_external_transceiver(argc, argv);
|
if (init_external_transceiver)
|
||||||
|
init_external_transceiver(app_data.trx, argc, argv);
|
||||||
// while (!app_data.quit)
|
else
|
||||||
// osmo_select_main(0);
|
while (!app_data.quit)
|
||||||
|
osmo_select_main(0);
|
||||||
gshutdown = true;
|
|
||||||
stop_trx();
|
|
||||||
|
|
||||||
|
if (close_external_transceiver)
|
||||||
|
close_external_transceiver(argc, argv);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
/* Close active connections */
|
/* Close active connections */
|
||||||
|
|
Loading…
Reference in New Issue