blob: c00d07276dffbf31a75cef07270e4b5d23ed9242 [file] [log] [blame]
#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;
};