Commit dd2cefa4 authored by Raymond Knopp's avatar Raymond Knopp

added longer prefix in PRACH symbol zero period for 15/30 kHz SCS. Both gNB...

added longer prefix in PRACH symbol zero period for 15/30 kHz SCS. Both gNB and UE processing is modified. prachsim is functional again with new FAPI interfaces.
parent 46c2c119
......@@ -1578,7 +1578,11 @@ void *ru_thread( void *param ) {
// Do PRACH RU processing
int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST);
if (prach_id>=0) {
rx_nr_prach_ru(ru,ru->prach_list[prach_id].fmt,proc->frame_rx,proc->tti_rx);
rx_nr_prach_ru(ru,
ru->prach_list[prach_id].fmt,
ru->prach_list[prach_id].numRA,
ru->prach_list[prach_id].prachStartSymbol,
proc->frame_rx,proc->tti_rx);
free_nr_ru_prach_entry(ru,prach_id);
}
}
......
......@@ -387,7 +387,7 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,
fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value);
fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000);
fp->nr_band = 78;
fp->threequarter_fs= 0;
// fp->threequarter_fs= 0;
gNB_config->carrier_config.dl_bandwidth.value = config_bandwidth(mu, N_RB_DL, fp->nr_band);
......
This diff is collapsed.
......@@ -122,6 +122,8 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
void rx_nr_prach_ru(RU_t *ru,
int prach_fmt,
int numRA,
int prachStartSymbol,
int frame,
int subframe);
......
......@@ -41,6 +41,8 @@
#include "T.h"
#define NR_PRACH_DEBUG 1
extern uint16_t NCS_unrestricted_delta_f_RA_125[16];
extern uint16_t NCS_restricted_TypeA_delta_f_RA_125[15];
extern uint16_t NCS_restricted_TypeB_delta_f_RA_125[13];
......@@ -111,7 +113,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
#else //normal case (simulation)
prach_start = subframe*(fp->samples_per_slot<<1)-ue->N_TA_offset;
LOG_D(PHY,"[UE %d] prach_start %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", ue->Mod_id,
LOG_I(PHY,"[UE %d] prach_start %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", ue->Mod_id,
prach_start,
ue->rx_offset,
ue->hw_timing_advance,
......@@ -222,7 +224,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
#ifdef NR_PRACH_DEBUG
if (NCS>0)
LOG_D(PHY,"Generate PRACH for RootSeqIndex %d, Preamble Index %d, PRACH Format %x, prach_ConfigIndex %d, NCS %d (NCS_config %d, N_ZC/NCS %d): Preamble_offset %d, Preamble_shift %d\n",
LOG_I(PHY,"Generate PRACH for RootSeqIndex %d, Preamble Index %d, PRACH Format %x, prach_ConfigIndex %d, NCS %d (NCS_config %d, N_ZC/NCS %d): Preamble_offset %d, Preamble_shift %d\n",
rootSequenceIndex,preamble_index,prach_fmt,prach_ConfigIndex,NCS,Ncs_config,N_ZC/NCS,
preamble_offset,preamble_shift);
......@@ -251,7 +253,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
k*=K;
k+=kbar;
LOG_D(PHY,"placing prach in position %d\n",k);
LOG_I(PHY,"placing prach in position %d\n",k);
k*=2;
Xu = (int16_t*)ue->X_u[preamble_offset-first_nonzero_root_idx];
......@@ -427,6 +429,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
dftlen=12288;
}
else if (prach_fmt == 0xa1 || prach_fmt == 0xb1 || prach_fmt == 0xc0) {
Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft2048(prachF,prach2,1);
dftlen=2048;
......@@ -440,6 +443,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
// here we have |Prefix | Prach2048 | Prach2048 (if ! 0xc0) |
}
else if (prach_fmt == 0xa2 || prach_fmt == 0xb2) { // 6x2048
Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft2048(prachF,prach2,1);
dftlen=2048;
// here we have |empty | Prach2048 |
......@@ -452,6 +457,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
prach_len = (2048*4)+Ncp;
}
else if (prach_fmt == 0xa3 || prach_fmt == 0xb3) { // 6x2048
Ncp+=32;
prach2 = prach+(Ncp<<1);
idft2048(prachF,prach2,1);
dftlen=2048;
......@@ -467,6 +473,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
prach_len = (2048*6)+Ncp;
}
else if (prach_fmt == 0xb4) { // 12x2048
Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft2048(prachF,prach2,1);
dftlen=2048;
// here we have |empty | Prach2048 |
......@@ -527,6 +535,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
prach_len = (9216*4)+Ncp;
}
else if (prach_fmt == 0xa1 || prach_fmt == 0xb1 || prach_fmt == 0xc0) {
Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft1536(prachF,prach2,1);
dftlen=1536;
// here we have |empty | Prach1536 |
......@@ -540,6 +550,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
}
else if (prach_fmt == 0xa2 || prach_fmt == 0xb2) { // 6x1536
Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft1536(prachF,prach2,1);
dftlen=1536;
// here we have |empty | Prach1536 |
......@@ -552,6 +564,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
prach_len = (1536*4)+Ncp;
}
else if (prach_fmt == 0xa3 || prach_fmt == 0xb3) { // 6x1536
Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft1536(prachF,prach2,1);
dftlen=1536;
// here we have |empty | Prach1536 |
......@@ -566,6 +580,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
prach_len = (1536*6)+Ncp;
}
else if (prach_fmt == 0xb4) { // 12x1536
Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft1536(prachF,prach2,1);
dftlen=1536;
// here we have |empty | Prach1536 |
......@@ -627,6 +643,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
prach_len = (24576*4)+Ncp;
}
else if (prach_fmt == 0xa1 || prach_fmt == 0xb1 || prach_fmt == 0xc0) {
Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft4096(prachF,prach2,1);
dftlen=4096;
// here we have |empty | Prach4096 |
......@@ -640,6 +658,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
}
else if (prach_fmt == 0xa2 || prach_fmt == 0xb2) { // 4x4096
Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft4096(prachF,prach2,1);
dftlen=4096;
// here we have |empty | Prach4096 |
......@@ -652,6 +672,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
prach_len = (4096*4)+Ncp;
}
else if (prach_fmt == 0xa3 || prach_fmt == 0xb3) { // 6x4096
Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft4096(prachF,prach2,1);
dftlen=4096;
// here we have |empty | Prach4096 |
......@@ -666,6 +688,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
prach_len = (4096*6)+Ncp;
}
else if (prach_fmt == 0xb4) { // 12x4096
Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft4096(prachF,prach2,1);
dftlen=4096;
// here we have |empty | Prach4096 |
......@@ -725,6 +749,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
prach_len = (18432*4)+Ncp;
}
else if (prach_fmt == 0xa1 || prach_fmt == 0xb1 || prach_fmt == 0xc0) {
Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft3072(prachF,prach2,1);
dftlen=3072;
// here we have |empty | Prach3072 |
......@@ -737,6 +763,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
// here we have |Prefix | Prach3072 | Prach3072 (if ! 0xc0) |
}
else if (prach_fmt == 0xa3 || prach_fmt == 0xb3) { // 6x3072
Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft3072(prachF,prach2,1);
dftlen=3072;
// here we have |empty | Prach3072 |
......@@ -751,6 +779,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
prach_len = (3072*6)+Ncp;
}
else if (prach_fmt == 0xa2 || prach_fmt == 0xb2) { // 4x3072
Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft3072(prachF,prach2,1);
dftlen=3072;
// here we have |empty | Prach3072 |
......@@ -763,6 +793,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe)
prach_len = (3072*4)+Ncp;
}
else if (prach_fmt == 0xb4) { // 12x3072
Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
prach2 = prach+(Ncp<<1);
idft3072(prachF,prach2,1);
dftlen=3072;
// here we have |empty | Prach3072 |
......
......@@ -193,6 +193,8 @@ typedef struct {
int frame;
int slot;
int fmt;
int numRA;
int prachStartSymbol;
} RU_PRACH_list_t;
#define NUMBER_OF_NR_RU_PRACH_MAX 8
......
......@@ -212,9 +212,7 @@ void nr_dump_dlsch_SI(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,
#endif
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)
unsigned int gain_table[31] = {100,112,126,141,158,178,200,224,251,282,316,359,398,447,501,562,631,708,794,891,1000,1122,1258,1412,1585,1778,1995,2239,2512,2818,3162};
#endif
int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){
......@@ -4490,7 +4488,7 @@ uint8_t nr_is_ri_TXOp(PHY_VARS_NR_UE *ue,
void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, runmode_t runmode) {
int frame_tx = proc->frame_tx, nr_tti_tx = proc->nr_tti_tx, prach_power, tx_amp;
uint16_t preamble_tx = 50, pathloss;
uint16_t /*preamble_tx = 50,*/ pathloss;
uint8_t mod_id = ue->Mod_id;
UE_MODE_t UE_mode = get_nrUE_mode(mod_id, ue->CC_id, gNB_id);
NR_PRACH_RESOURCES_t * prach_resources = ue->prach_resources[gNB_id];
......@@ -4499,7 +4497,7 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t
ue->generate_nr_prach = 0;
if (ue->mac_enabled == 0){
prach_resources->ra_PreambleIndex = preamble_tx;
// prach_resources->ra_PreambleIndex = preamble_tx;
prach_resources->ra_TDD_map_index = 0;
prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = 10;
prach_resources->ra_RNTI = 0x1234;
......
......@@ -55,4 +55,15 @@ signed char quantize(double D, double x, unsigned char B) {
return ((char) qxd);
}
int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe) {
AssertFatal(1==0,"Shouldn't be here ...\n");
return 0;
}
int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) {return(0);}
NR_IF_Module_t *NR_IF_Module_init(int Mod_id){return(NULL);}
int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); }
#endif
......@@ -42,11 +42,15 @@
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/INIT/phy_init.h"
#include "PHY/NR_TRANSPORT/nr_transport.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto_common.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "nr_unitary_defs.h"
#include "OCG_vars.h"
#include <pthread.h>
PHY_VARS_gNB *gNB;
PHY_VARS_NR_UE *UE;
RAN_CONTEXT_t RC;
......@@ -59,27 +63,33 @@ extern uint16_t prach_root_sequence_map0_3[838];
void dump_nr_prach_config(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe);
uint16_t NB_UE_INST=1;
volatile int oai_exit=0;
void exit_function(const char* file, const char* function, const int line,const char *s) {
const char * msg= s==NULL ? "no comment": s;
printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg);
exit(-1);
}
int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe) {
AssertFatal(1==0,"Shouldn't be here ...\n");
return 0;
}
int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) {return(0);}
openair0_config_t openair0_cfg[MAX_CARDS];
uint8_t nfapi_mode=0;
NR_IF_Module_t *NR_IF_Module_init(int Mod_id){return(NULL);}
int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); }
void nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
module_id_t mod_id,
int CC_id,
UE_MODE_t UE_mode,
frame_t frame,
uint8_t gNB_id,
int nr_tti_tx) { return;}
void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id) { return;}
uint16_t nr_ue_process_rar(module_id_t mod_id,
int CC_id,
frame_t frameP,
uint8_t * dlsch_buffer,
rnti_t * t_crnti,
uint8_t preamble_index,
uint8_t * selected_rar_buffer) { return 0;}
int is_nr_prach_subframe(NR_DL_FRAME_PARMS *fp,uint32_t frame,uint8_t slot) { return(1);}
int get_nr_prach_fmt(int prachConfigIndex,int frame_type,int fr) { return(0xa2); }
int main(int argc, char **argv)
{
......@@ -203,7 +213,7 @@ int main(int argc, char **argv)
break;
default:
msg("Unsupported channel model!\n");
printf("Unsupported channel model!\n");
exit(-1);
}
......@@ -219,13 +229,13 @@ int main(int argc, char **argv)
case 's':
snr0 = atof(optarg);
msg("Setting SNR0 to %f\n",snr0);
printf("Setting SNR0 to %f\n",snr0);
break;
case 'S':
snr1 = atof(optarg);
snr1set=1;
msg("Setting SNR1 to %f\n",snr1);
printf("Setting SNR1 to %f\n",snr1);
break;
case 'p':
......@@ -268,7 +278,7 @@ int main(int argc, char **argv)
if ((transmission_mode!=1) &&
(transmission_mode!=2) &&
(transmission_mode!=6)) {
msg("Unsupported transmission mode %d\n",transmission_mode);
printf("Unsupported transmission mode %d\n",transmission_mode);
exit(-1);
}
......@@ -278,7 +288,7 @@ int main(int argc, char **argv)
n_tx=atoi(optarg);
if ((n_tx==0) || (n_tx>2)) {
msg("Unsupported number of tx antennas %d\n",n_tx);
printf("Unsupported number of tx antennas %d\n",n_tx);
exit(-1);
}
......@@ -288,7 +298,7 @@ int main(int argc, char **argv)
n_rx=atoi(optarg);
if ((n_rx==0) || (n_rx>2)) {
msg("Unsupported number of rx antennas %d\n",n_rx);
printf("Unsupported number of rx antennas %d\n",n_rx);
exit(-1);
}
......@@ -400,10 +410,24 @@ int main(int argc, char **argv)
ru->nb_tx = n_tx;
ru->nb_rx = n_rx;
gNB->gNB_config.carrier_config.num_tx_ant.value=1;
gNB->gNB_config.carrier_config.num_rx_ant.value=1;
gNB->gNB_config.prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(gNB->gNB_config.prach_config.num_prach_fd_occasions.value*sizeof(nfapi_nr_num_prach_fd_occasions_t));
gNB->gNB_config.prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index.value = 1;
gNB->gNB_config.prach_config.num_prach_fd_occasions_list[0].num_root_sequences.value = 16;
gNB->gNB_config.prach_config.prach_sequence_length.value = 1;
gNB->gNB_config.prach_config.num_prach_fd_occasions_list[0].k1.value = 0;
gNB->gNB_config.prach_config.restricted_set_config.value = 0;
gNB->gNB_config.tdd_table.tdd_period.value = 6;
memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config));
RC.nb_nr_L1_inst=1;
phy_init_nr_gNB(gNB,0,0);
nr_phy_init_RU(ru);
set_tdd_config_nr(&gNB->gNB_config, 5000,
set_tdd_config_nr(&gNB->gNB_config, 1,
7, 6,
2, 4);
......@@ -481,21 +505,9 @@ int main(int argc, char **argv)
gNB->common_vars.rxdata = ru->common.rxdata;
compute_nr_prach_seq(gNB->frame_parms.prach_config_common.rootSequenceIndex,
gNB->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex,
gNB->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig,
gNB->frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag,
gNB->frame_parms.frame_type,
gNB->frame_parms.freq_range,
gNB->X_u);
compute_nr_prach_seq(&gNB->gNB_config,0,gNB->X_u);
compute_nr_prach_seq(UE->frame_parms.prach_config_common.rootSequenceIndex,
UE->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex,
UE->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig,
UE->frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag,
UE->frame_parms.frame_type,
UE->frame_parms.freq_range,
UE->X_u);
compute_nr_prach_seq(&gNB->gNB_config,0,UE->X_u);
......@@ -517,6 +529,7 @@ int main(int argc, char **argv)
subframe); */ //commented for testing purpose
UE_nr_rxtx_proc_t proc={0};
proc.frame_tx=0;proc.nr_tti_tx=subframe;
nr_ue_prach_procedures(UE,&proc,0,0);
/* tx_lev_dB not used later, no need to set */
......@@ -526,7 +539,7 @@ int main(int argc, char **argv)
//LOG_M("txsig1.m","txs1", txdata[1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1);
// multipath channel
dump_nr_prach_config(&gNB->frame_parms,subframe);
// dump_nr_prach_config(&gNB->frame_parms,subframe);
for (i=0; i<frame_parms->samples_per_slot<<1; i++) {
for (aa=0; aa<1; aa++) {
......@@ -589,17 +602,25 @@ int main(int argc, char **argv)
}
uint16_t preamble_rx;
rx_nr_prach_ru(ru,
1,
0,
subframe);
0,
0,
subframe<<1);
gNB->prach_vars.rxsigF = ru->prach_rxsigF;
nfapi_nr_prach_pdu_t prach_pdu;
prach_pdu.num_cs = 34;
prach_pdu.prach_format = 1; // A2
rx_nr_prach(gNB,
&prach_pdu,
0,
subframe,
subframe<<1,
&preamble_rx,
&preamble_energy,
&preamble_delay);
printf("preamble_rx %d\n", preamble_rx);
if (preamble_rx!=preamble_tx)
prach_errors++;
else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment