Commit 591522ec authored by Guy De Souza's avatar Guy De Souza

nfapi changes/payload scrambling

parent 47710949
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
#include "nfapi_interface.h" #include "nfapi_interface.h"
#define NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS 5
// nFAPI enums // nFAPI enums
typedef enum { typedef enum {
NFAPI_NR_DL_CONFIG_DCI_DL_PDU_TYPE = 0, NFAPI_NR_DL_CONFIG_DCI_DL_PDU_TYPE = 0,
...@@ -283,7 +286,7 @@ uint8_t beta_offset_indicator; //0 or 2 bits ...@@ -283,7 +286,7 @@ uint8_t beta_offset_indicator; //0 or 2 bits
uint8_t dmrs_sequence_initialization; //0 or 1 bit uint8_t dmrs_sequence_initialization; //0 or 1 bit
uint8_t ul_sch_indicator; //1 bit uint8_t ul_sch_indicator; //1 bit
} nfapi_nr_ul_config_dci_ul_pdu_rel15_t; } nfapi_nr_ul_config_dci_pdu_rel15_t;
//#define NFAPI_NR_UL_CONFIG_REQUEST_DCI_UL_PDU_REL15_TAG 0x???? //#define NFAPI_NR_UL_CONFIG_REQUEST_DCI_UL_PDU_REL15_TAG 0x????
//formats 1_0, 1_1, 2_0, 2_1, 2_2 and 2_3 //formats 1_0, 1_1, 2_0, 2_1, 2_2 and 2_3
...@@ -340,39 +343,41 @@ uint16_t *pre_emption_indications; //14 bit ...@@ -340,39 +343,41 @@ uint16_t *pre_emption_indications; //14 bit
uint8_t block_number_count; uint8_t block_number_count;
uint8_t *block_numbers; uint8_t *block_numbers;
} nfapi_nr_dl_config_dci_dl_pdu_rel15_t; } nfapi_nr_dl_config_dci_pdu_rel15_t;
//#define NFAPI_NR_DL_CONFIG_REQUEST_DCI_DL_PDU_REL15_TAG 0x???? //#define NFAPI_NR_DL_CONFIG_REQUEST_DCI_DL_PDU_REL15_TAG 0x????
typedef struct{ typedef struct{
nfapi_uint16_tlv_t controlResourceSetId; ///// L1 parameter 'CORESET-ID' nfapi_uint16_tlv_t coreset_id; ///// L1 parameter 'CORESET-ID'
nfapi_uint16_tlv_t frequencyDomainResources; ///// L1 parameter 'CORESET-freq-dom' nfapi_uint16_tlv_t frequency_domain_resources; ///// L1 parameter 'CORESET-freq-dom'
nfapi_uint16_tlv_t duration; ///// L1 parameter 'CORESET-time-duration' nfapi_uint16_tlv_t duration; ///// L1 parameter 'CORESET-time-duration'
nfapi_uint16_tlv_t cce_REG_MappingType; ///// L1 parameter 'CORESET-CCE-REG-mapping-type' nfapi_uint16_tlv_t cce_reg_mapping_ype; ///// L1 parameter 'CORESET-CCE-REG-mapping-type'
nfapi_uint16_tlv_t reg_BundleSize; ///// L1 parameter 'CORESET-REG-bundle-size' nfapi_uint16_tlv_t reg_bundle_size; ///// L1 parameter 'CORESET-REG-bundle-size'
nfapi_uint16_tlv_t interleaverSize; ///// L1 parameter 'CORESET-interleaver-size' nfapi_uint16_tlv_t interleaver_size; ///// L1 parameter 'CORESET-interleaver-size'
nfapi_uint16_tlv_t shiftIndex; ///// L1 parameter 'CORESET-shift-index' nfapi_uint16_tlv_t shift_index; ///// L1 parameter 'CORESET-shift-index'
nfapi_uint16_tlv_t precoderGranularity; ///// L1 parameter 'CORESET-precoder-granuality' nfapi_uint16_tlv_t precoder_granularity; ///// L1 parameter 'CORESET-precoder-granuality'
nfapi_uint16_tlv_t TCI_StateId; ///// L1 parameter 'TCI-StatesPDCCH' nfapi_uint16_tlv_t tci_state_id; ///// L1 parameter 'TCI-StatesPDCCH'
nfapi_uint16_tlv_t tci_PresentInDCI; ///// L1 parameter 'TCI-PresentInDCI' nfapi_uint16_tlv_t tci_present_in_dci; ///// L1 parameter 'TCI-PresentInDCI'
nfapi_uint16_tlv_t pdcch_DMRS_ScramblingID; ///// L1 parameter 'PDCCH-DMRS-Scrambling-ID' nfapi_uint16_tlv_t pdcch_dmrs_scrambling_id; ///// L1 parameter 'PDCCH-DMRS-Scrambling-ID'
} nfapi_nr_ControlResourcesSets_t; } nfapi_nr_coreset_t;
typedef struct{ typedef struct{
nfapi_uint16_tlv_t SearchSpaceId; nfapi_uint16_tlv_t search_space_id;
nfapi_uint16_tlv_t controlResourceSetId; nfapi_uint16_tlv_t coreset_id;
nfapi_uint16_tlv_t monitoringSlotPeriodicityAndOffset; ///// L1 parameters 'Montoring-periodicity-PDCCH-slot' nfapi_uint16_tlv_t monitoring_slot_periodicity_and_offset; ///// L1 parameters 'Montoring-periodicity-PDCCH-slot'
nfapi_uint16_tlv_t monitoringSymbolsWithinSlot; ///// L1 parameter 'Montoring-symbols-PDCCH-within-slot' nfapi_uint16_tlv_t monitoring_symbols_within_slot; ///// L1 parameter 'Montoring-symbols-PDCCH-within-slot'
nfapi_uint16_tlv_t nrofCand_aggLevel1; ///// L1 parameter 'Aggregation-level-1' nfapi_uint16_tlv_t number_of_candidates[NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS]; ///// L1 parameter 'Aggregation-level-1/2/4/8/16'
nfapi_uint16_tlv_t nrofCand_aggLevel2; ///// L1 parameter 'Aggregation-level-2'
nfapi_uint16_tlv_t nrofCand_aggLevel4; ///// L1 parameter 'Aggregation-level-4'
nfapi_uint16_tlv_t nrofCand_aggLevel8; ///// L1 parameter 'Aggregation-level-8'
nfapi_uint16_tlv_t nrofCand_aggLevel16; ///// L1 parameter 'Aggregation-level-16'
nfapi_uint16_tlv_t Com_dci_Format2_0_nrofCand_SFI_And_aggLevel; ///// L1 parameters 'SFI-Num-PDCCH-cand' and 'SFI-Aggregation-Level' nfapi_uint16_tlv_t Com_dci_Format2_0_nrofCand_SFI_And_aggLevel; ///// L1 parameters 'SFI-Num-PDCCH-cand' and 'SFI-Aggregation-Level'
nfapi_uint16_tlv_t Com_dci_Format2_3_monitoringPeriodicity; ///// L1 parameter 'SRS-monitoring-periodicity' nfapi_uint16_tlv_t Com_dci_Format2_3_monitoringPeriodicity; ///// L1 parameter 'SRS-monitoring-periodicity'
nfapi_uint16_tlv_t Com_dci_Format2_3_nrofPDCCH_Candidates; ///// L1 parameter 'SRS-Num-PDCCH-cand' nfapi_uint16_tlv_t Com_dci_Format2_3_nrofPDCCH_Candidates; ///// L1 parameter 'SRS-Num-PDCCH-cand'
nfapi_uint16_tlv_t ue_Specific_dci_Formats; nfapi_uint16_tlv_t ue_Specific_dci_Formats;
} nfapi_nr_SearchSpaces_t; } nfapi_nr_search_space_t;
typedef struct {
nfapi_tl_t tl;
nfapi_nr_search_space_t search_space;
} nfapi_nr_dl_config_pdcch_parameters_rel15_t;
typedef struct { typedef struct {
nfapi_tl_t tl; nfapi_tl_t tl;
...@@ -385,18 +390,18 @@ typedef struct { ...@@ -385,18 +390,18 @@ typedef struct {
typedef struct { typedef struct {
nfapi_tl_t tl; nfapi_tl_t tl;
nfapi_nr_SearchSpaces_t sib1searchSpace; nfapi_nr_search_space_t sib1searchSpace;
nfapi_nr_ControlResourcesSets_t sib1ControlResourceSets; nfapi_nr_coreset_t sib1ControlResourceSets;
nfapi_nr_SearchSpaces_t sibssearchSpace; nfapi_nr_search_space_t sibssearchSpace;
nfapi_nr_ControlResourcesSets_t sibsControlResourceSets; nfapi_nr_coreset_t sibsControlResourceSets;
nfapi_nr_SearchSpaces_t ra_SearchSpace; nfapi_nr_search_space_t ra_SearchSpace;
nfapi_nr_ControlResourcesSets_t ra_ControlResourceSets; nfapi_nr_coreset_t ra_ControlResourceSets;
}nfapi_nr_dl_config_dlsch_pdu_rel15_t; }nfapi_nr_dl_config_dlsch_pdu_rel15_t;
typedef struct { typedef struct {
nfapi_tl_t tl; nfapi_tl_t tl;
nfapi_nr_SearchSpaces_t pagingSearchSpace; nfapi_nr_search_space_t pagingSearchSpace;
nfapi_nr_ControlResourcesSets_t pagingControlResourceSets; nfapi_nr_coreset_t pagingControlResourceSets;
}nfapi_nr_dl_config_pch_pdu_rel15_t; }nfapi_nr_dl_config_pch_pdu_rel15_t;
typedef struct { typedef struct {
...@@ -411,12 +416,14 @@ typedef struct { ...@@ -411,12 +416,14 @@ typedef struct {
}nfapi_nr_dl_config_ndlsch_pdu_rel15_t; }nfapi_nr_dl_config_ndlsch_pdu_rel15_t;
typedef struct { typedef struct {
uint8_t pdu_type; uint8_t pdu_type;
uint8_t pdu_size; uint8_t pdu_size;
union { union {
nfapi_nr_dl_config_dci_dl_pdu_rel15_t dci_dl_pdu_rel15; nfapi_nr_dl_config_dci_pdu_rel15_t dci_dl_pdu_rel15;
nfapi_nr_ul_config_dci_ul_pdu_rel15_t dci_ul_pdu_rel15; nfapi_nr_ul_config_dci_pdu_rel15_t dci_ul_pdu_rel15;
nfapi_nr_dl_config_bch_pdu_rel15_t bch_pdu_rel15; nfapi_nr_dl_config_bch_pdu_rel15_t bch_pdu_rel15;
nfapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_pdu_rel15; nfapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_pdu_rel15;
nfapi_nr_dl_config_pch_pdu_rel15_t pch_pdu_rel15; nfapi_nr_dl_config_pch_pdu_rel15_t pch_pdu_rel15;
...@@ -424,6 +431,8 @@ typedef struct { ...@@ -424,6 +431,8 @@ typedef struct {
nfapi_nr_dl_config_npdcch_pdu_rel15_t npdcch_pdu_rel15; nfapi_nr_dl_config_npdcch_pdu_rel15_t npdcch_pdu_rel15;
nfapi_nr_dl_config_ndlsch_pdu_rel15_t ndlsch_pdu_rel15; nfapi_nr_dl_config_ndlsch_pdu_rel15_t ndlsch_pdu_rel15;
}; };
nfapi_nr_dl_config_pdcch_parameters_rel15_t pdcch_params_rel15;
} nfapi_nr_dl_config_request_pdu_t; } nfapi_nr_dl_config_request_pdu_t;
typedef struct { typedef struct {
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT]; extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT];
uint8_t nr_get_dci_size(nr_dci_format_e format, uint8_t nr_get_dci_size(nr_dci_format_e format,
nr_rnti_type_e rnti, nr_rnti_type_e rnti_type,
NR_BWP_PARMS* bwp, NR_BWP_PARMS* bwp,
nfapi_nr_config_request_t* config) nfapi_nr_config_request_t* config)
{ {
...@@ -50,7 +50,7 @@ uint8_t nr_get_dci_size(nr_dci_format_e format, ...@@ -50,7 +50,7 @@ uint8_t nr_get_dci_size(nr_dci_format_e format,
case nr_dci_format_0_0: case nr_dci_format_0_0:
/// fixed: Format identifier 1, Hop flag 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2 Time Domain assgnmt 4 --20 /// fixed: Format identifier 1, Hop flag 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2 Time Domain assgnmt 4 --20
size += 20; size += 20;
size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>2 ) ); // Freq domain assignment -- hopping scenario to be updated size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment -- hopping scenario to be updated
// UL/SUL indicator assumed to be 0 // UL/SUL indicator assumed to be 0
// Padding // Padding
break; break;
...@@ -80,7 +80,7 @@ uint8_t nr_get_dci_size(nr_dci_format_e format, ...@@ -80,7 +80,7 @@ uint8_t nr_get_dci_size(nr_dci_format_e format,
case nr_dci_format_1_0: case nr_dci_format_1_0:
/// fixed: Format identifier 1, VRB2PRB 1, MCS 5, NDI 1, RV 2, HARQ PID 4, DAI 2, PUCCH TPC 2, PUCCH RInd 3, PDSCH to HARQ TInd 3 --24 /// fixed: Format identifier 1, VRB2PRB 1, MCS 5, NDI 1, RV 2, HARQ PID 4, DAI 2, PUCCH TPC 2, PUCCH RInd 3, PDSCH to HARQ TInd 3 --24
size += 24; size += 24;
size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>2 ) ); // Freq domain assignment size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment
// Time domain assignment // Time domain assignment
break; break;
...@@ -130,12 +130,37 @@ uint8_t nr_get_dci_size(nr_dci_format_e format, ...@@ -130,12 +130,37 @@ uint8_t nr_get_dci_size(nr_dci_format_e format,
return size; return size;
} }
void nr_pdcch_scrambling(NR_gNB_DCI_ALLOC_t dci_alloc,
nr_pdcch_vars_t pdcch_vars,
nfapi_nr_config_request_t config,
uint32_t* out) {
uint8_t reset;
uint32_t x1, x2, s=0;
uint32_t Nid = (dci_alloc.ss_type == nr_pdcch_uss_type)? pdcch_vars.dmrs_scrambling_id : config.sch_config.physical_cell_id.value;
uint32_t n_RNTI = (dci_alloc.ss_type == nr_pdcch_uss_type)? dci_alloc.rnti : 0;
uint32_t *in = dci_alloc.dci_pdu;
reset = 1;
x2 = (n_RNTI<<16) + Nid;
for (int i=0; i<dci_alloc.size; i++) {
if ((i&0x1f)==0) {
s = lte_gold_generic(&x1, &x2, reset);
reset = 0;
}
*out ^= (((*in)>>i)&1) ^ ((s>>i)&1);
}
}
uint8_t nr_generate_dci_top(NR_gNB_DCI_ALLOC_t dci_alloc, uint8_t nr_generate_dci_top(NR_gNB_DCI_ALLOC_t dci_alloc,
uint32_t *gold_pdcch_dmrs, uint32_t *gold_pdcch_dmrs,
int32_t** txdataF, int32_t** txdataF,
int16_t amp, int16_t amp,
NR_DL_FRAME_PARMS* frame_parms, NR_DL_FRAME_PARMS frame_parms,
nfapi_nr_config_request_t* config) nfapi_nr_config_request_t config,
nr_pdcch_vars_t pdcch_vars)
{ {
uint16_t mod_dmrs[NR_MAX_PDCCH_DMRS_LENGTH<<1]; uint16_t mod_dmrs[NR_MAX_PDCCH_DMRS_LENGTH<<1];
...@@ -152,5 +177,13 @@ uint8_t nr_generate_dci_top(NR_gNB_DCI_ALLOC_t dci_alloc, ...@@ -152,5 +177,13 @@ uint8_t nr_generate_dci_top(NR_gNB_DCI_ALLOC_t dci_alloc,
#endif #endif
} }
/// DCI payload processing
// scrambling
uint32_t scrambled_payload[4];
nr_pdcch_scrambling(dci_alloc, pdcch_vars, config, scrambled_payload);
// QPSK modulation
return 0; return 0;
} }
...@@ -61,6 +61,11 @@ typedef enum { ...@@ -61,6 +61,11 @@ typedef enum {
nr_ssb_and_cset_mux_pattern_type_3 nr_ssb_and_cset_mux_pattern_type_3
} nr_ssb_and_cset_mux_pattern_type_e; } nr_ssb_and_cset_mux_pattern_type_e;
typedef enum {
nr_cce_reg_mapping_interleaved=0,
nr_cce_reg_mapping_non_interleaved
} nr_cce_reg_mapping_type_e;
typedef struct { typedef struct {
uint8_t param_O; uint8_t param_O;
uint8_t param_M; uint8_t param_M;
...@@ -80,6 +85,8 @@ typedef struct { ...@@ -80,6 +85,8 @@ typedef struct {
uint8_t first_slot; uint8_t first_slot;
uint8_t nb_slots; uint8_t nb_slots;
uint8_t sfn_mod2; uint8_t sfn_mod2;
uint32_t dmrs_scrambling_id;
nr_cce_reg_mapping_type_e cr_mapping_type;
nr_pdcch_ss_params_t ss_params; nr_pdcch_ss_params_t ss_params;
nr_pdcch_coreset_params_t coreset_params; nr_pdcch_coreset_params_t coreset_params;
} nr_pdcch_vars_t; } nr_pdcch_vars_t;
...@@ -89,22 +96,20 @@ typedef struct { ...@@ -89,22 +96,20 @@ typedef struct {
uint8_t size; uint8_t size;
/// Aggregation level /// Aggregation level
uint8_t L; uint8_t L;
/// Position of first CCE of the dci /// rnti type
int firstCCE;
/// flag to indicate that this is a RA response
boolean_t ra_flag;
/// rnti
nr_rnti_type_e rnti; nr_rnti_type_e rnti;
/// Format /// Format
DCI_format_t format; nr_dci_format_e format;
/// type
nr_pdcch_ss_type_e ss_type;
/// DCI pdu /// DCI pdu
uint8_t dci_pdu[8]; uint32_t dci_pdu[4];
} NR_gNB_DCI_ALLOC_t; } NR_gNB_DCI_ALLOC_t;
typedef unsigned __int128 uint128_t; typedef unsigned __int128 uint128_t;
uint8_t nr_get_dci_size(nr_dci_format_e format, uint8_t nr_get_dci_size(nr_dci_format_e format,
nr_rnti_type_e rnti, nr_rnti_type_e rnti_type,
NR_BWP_PARMS* bwp, NR_BWP_PARMS* bwp,
nfapi_nr_config_request_t* config); nfapi_nr_config_request_t* config);
...@@ -112,7 +117,13 @@ uint8_t nr_generate_dci_top(NR_gNB_DCI_ALLOC_t dci_alloc, ...@@ -112,7 +117,13 @@ uint8_t nr_generate_dci_top(NR_gNB_DCI_ALLOC_t dci_alloc,
uint32_t *gold_pdcch_dmrs, uint32_t *gold_pdcch_dmrs,
int32_t** txdataF, int32_t** txdataF,
int16_t amp, int16_t amp,
NR_DL_FRAME_PARMS* frame_parms, NR_DL_FRAME_PARMS frame_parms,
nfapi_nr_config_request_t* config); nfapi_nr_config_request_t config,
nr_pdcch_vars_t pdcch_vars);
void nr_pdcch_scrambling(NR_gNB_DCI_ALLOC_t dci_alloc,
nr_pdcch_vars_t pdcch_vars,
nfapi_nr_config_request_t config,
uint32_t* out);
#endif //__PHY_NR_TRANSPORT_DCI__H #endif //__PHY_NR_TRANSPORT_DCI__H
...@@ -60,7 +60,7 @@ nr_subframe_t nr_subframe_select(nfapi_nr_config_request_t *cfg,unsigned char su ...@@ -60,7 +60,7 @@ nr_subframe_t nr_subframe_select(nfapi_nr_config_request_t *cfg,unsigned char su
} }
void nr_get_type0_coreset_and_ss_params(nr_pdcch_vars_t *pdcch_vars, void nr_get_pdcch_vars_from_mib(nr_pdcch_vars_t *pdcch_vars,
nr_scs_e scs_common, nr_scs_e scs_common,
nr_scs_e pdcch_scs, nr_scs_e pdcch_scs,
nr_frequency_range_e freq_range, nr_frequency_range_e freq_range,
...@@ -170,8 +170,17 @@ void nr_get_pdcch_type_0_monitoring_period(nr_pdcch_vars_t *pdcch_vars, ...@@ -170,8 +170,17 @@ void nr_get_pdcch_type_0_monitoring_period(nr_pdcch_vars_t *pdcch_vars,
pdcch_vars->sfn_mod2 = ((uint8_t)(floor( (O*pow(2, mu) + floor(ssb_idx*M)) / nb_slots_per_frame )) & 1)? 1 : 0; pdcch_vars->sfn_mod2 = ((uint8_t)(floor( (O*pow(2, mu) + floor(ssb_idx*M)) / nb_slots_per_frame )) & 1)? 1 : 0;
pdcch_vars->first_slot = (uint8_t)(O*pow(2, mu) + floor(ssb_idx*M)) % nb_slots_per_frame; pdcch_vars->first_slot = (uint8_t)(O*pow(2, mu) + floor(ssb_idx*M)) % nb_slots_per_frame;
} }
else { //nr_pdcch_mux_pattern_type_2, nr_pdcch_mux_pattern_type_3 else { //nr_ssb_and_cset_mux_pattern_type_2, nr_ssb_and_cset_mux_pattern_type_3
pdcch_vars->nb_slots = 1; pdcch_vars->nb_slots = 1;
} }
} }
void nr_get_pdcch_vars_from_config(nr_pdcch_vars_t* pdcch_vars,
nfapi_nr_coreset_t* coreset,
nfapi_nr_search_space_t* search_space) {
nr_pdcch_coreset_params_t cset_params = pdcch_vars->coreset_params;
nr_pdcch_ss_params_t ss_params = pdcch_vars->ss_params;
}
...@@ -181,6 +181,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, ...@@ -181,6 +181,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
//temporary DCI generation test //temporary DCI generation test
NR_gNB_DCI_ALLOC_t dci_alloc; NR_gNB_DCI_ALLOC_t dci_alloc;
nr_generate_dci_top(dci_alloc, gNB->nr_gold_pdcch_dmrs[0][0],gNB->common_vars.txdataF, 512, fp, cfg); nr_pdcch_vars_t pdcch_vars;
nr_generate_dci_top(dci_alloc, gNB->nr_gold_pdcch_dmrs[0][0],gNB->common_vars.txdataF, 512, *fp, *cfg, pdcch_vars);
} }
} }
...@@ -42,7 +42,7 @@ void nr_feptx_ofdm(RU_t *ru); ...@@ -42,7 +42,7 @@ void nr_feptx_ofdm(RU_t *ru);
void nr_feptx_ofdm_2thread(RU_t *ru); void nr_feptx_ofdm_2thread(RU_t *ru);
void nr_feptx0(RU_t *ru,int slot); void nr_feptx0(RU_t *ru,int slot);
void nr_get_type0_coreset_and_ss_params(nr_pdcch_vars_t *pdcch_vars, void nr_get_pdcch_vars_from_mib(nr_pdcch_vars_t *pdcch_vars,
nr_scs_e scs_common, nr_scs_e scs_common,
nr_scs_e pdcch_scs, nr_scs_e pdcch_scs,
nr_frequency_range_e freq_range, nr_frequency_range_e freq_range,
......
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