Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG UE
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Michael Black
OpenXG UE
Commits
3197c314
Commit
3197c314
authored
Sep 29, 2017
by
oai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'RU-RAU-split' of
https://gitlab.eurecom.fr/oai/openairinterface5g
into RU-RAU-split
parents
03dbb1a6
9aed4941
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
93 additions
and
59 deletions
+93
-59
openair1/PHY/LTE_TRANSPORT/pucch.c
openair1/PHY/LTE_TRANSPORT/pucch.c
+92
-58
openair2/LAYER2/MAC/eNB_scheduler_RA.c
openair2/LAYER2/MAC/eNB_scheduler_RA.c
+1
-1
No files found.
openair1/PHY/LTE_TRANSPORT/pucch.c
View file @
3197c314
...
...
@@ -1175,10 +1175,10 @@ uint16_t pucchfmt3_subCarrierDeMapping( PHY_VARS_eNB *eNB,
if
(
carrier_offset
==
frame_parms
->
ofdm_symbol_size
)
carrier_offset
=
0
;
#ifdef DEBUG_PUCCH_RX
/*
#ifdef DEBUG_PUCCH_RX
LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d,%d,%d) : (%d,%d)\n",subframe,l,k,carrier_offset,m,
SubCarrierDeMapData[aa][l][k][0],SubCarrierDeMapData[aa][l][k][1]);
#endif
#endif*/
}
}
}
...
...
@@ -1810,9 +1810,13 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
int16_t
tmp_re
,
tmp_im
,
W_re
=
0
,
W_im
=
0
;
int16_t
*
rxptr
;
uint32_t
symbol_offset
;
int16_t
stat_ref_re
,
stat_ref_im
,
*
cfo
,
chest_re
,
chest_im
;
int16_t
stat_ref_re
,
stat_ref_im
,
*
cfo
;
int16_t
chest0_re
[
NB_ANTENNAS_RX
][
12
],
chest0_im
[
NB_ANTENNAS_RX
][
12
];
int16_t
chest1_re
[
NB_ANTENNAS_RX
][
12
],
chest1_im
[
NB_ANTENNAS_RX
][
12
];
int32_t
chest_mag
;
int32_t
stat_re
=
0
,
stat_im
=
0
;
uint32_t
stat
,
stat_max
=
0
;
uint8_t
log2_maxh
;
uint8_t
deltaPUCCH_Shift
=
frame_parms
->
pucch_config_common
.
deltaPUCCH_Shift
;
uint8_t
NRB2
=
frame_parms
->
pucch_config_common
.
nRB_CQI
;
...
...
@@ -2194,6 +2198,10 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
for
(
aa
=
0
;
aa
<
frame_parms
->
nb_antennas_rx
;
aa
++
)
{
for
(
re
=
0
;
re
<
12
;
re
++
)
{
// compute received energy first slot, seperately for data and reference
// by coherent combining across symbols but not resource elements
// Note: assumption is that channel is stationary over symbols in slot after CFO
stat_re
=
0
;
stat_im
=
0
;
stat_ref_re
=
0
;
...
...
@@ -2219,9 +2227,15 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
stat_re
,
stat_im
);
#endif
}
// this is total energy received, summed over data and reference
stat
+=
((((
stat_re
*
stat_re
))
+
((
stat_im
*
stat_im
))
+
((
stat_ref_re
*
stat_ref_re
))
+
((
stat_ref_im
*
stat_ref_im
)))
/
nsymb
);
// now second slot
stat_re
=
0
;
stat_im
=
0
;
stat_ref_re
=
0
;
stat_ref_im
=
0
;
for
(
l2
=
0
,
l
=
(
nsymb
>>
1
);
l
<
(
nsymb
-
1
);
l
++
,
l2
++
)
{
if
((
l2
<
2
)
||
((
l2
>
(
nsymb
>>
1
)
-
3
))
)
{
// data symbols
...
...
@@ -2284,101 +2298,121 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
// Do detection now
if
(
sigma2_dB
<
(
dB_fixed
(
stat_max
)
-
pucch1_thres
))
{
//
*
Po_PUCCH
=
((
*
Po_PUCCH
*
1023
)
+
stat_max
)
>>
10
;
chL
=
(
nsymb
>>
1
)
-
4
;
chest_mag
=
0
;
cfo
=
(
frame_parms
->
Ncp
==
0
)
?
&
cfo_pucch_np
[
14
*
phase_max
]
:
&
cfo_pucch_ep
[
12
*
phase_max
];
for
(
aa
=
0
;
aa
<
frame_parms
->
nb_antennas_rx
;
aa
++
)
{
// channel estimates first
for
(
re
=
0
;
re
<
12
;
re
++
)
{
chest_re
=
0
;
chest_im
=
0
;
cfo
=
(
frame_parms
->
Ncp
==
0
)
?
&
cfo_pucch_np
[
14
*
phase_max
]
:
&
cfo_pucch_ep
[
12
*
phase_max
];
// channel estimate for first slot
chest0_re
[
aa
][
re
]
=
0
;
chest0_im
[
aa
][
re
]
=
0
;
for
(
l
=
2
;
l
<
(
nsymb
>>
1
)
-
2
;
l
++
)
{
off
=
(
re
<<
1
)
+
(
24
*
l
);
chest0_re
[
aa
][
re
]
+=
(((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
l
<<
1
])
>>
15
)
-
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
))
/
chL
;
chest0_im
[
aa
][
re
]
+=
(((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
)
+
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[(
l
<<
1
)])
>>
15
))
/
chL
;
}
// channel estimate for second slot
chest1_re
[
aa
][
re
]
=
0
;
chest1_im
[
aa
][
re
]
=
0
;
for
(
l
=
2
;
l
<
(
nsymb
>>
1
)
-
2
;
l
++
)
{
off
=
(
re
<<
1
)
+
(
24
*
l
);
chest
_re
+=
(((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
l
<<
1
])
>>
15
)
-
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
))
/
chL
;
chest
_im
+=
(((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
)
+
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[(
l
<<
1
)])
>>
15
))
/
chL
;
off
=
(
re
<<
1
)
+
(
24
*
l
)
+
(
nsymb
>>
1
)
*
24
;
chest
1_re
[
aa
][
re
]
+=
(((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
l
<<
1
])
>>
15
)
-
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
))
/
chL
;
chest
1_im
[
aa
][
re
]
+=
(((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
)
+
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[(
l
<<
1
)])
>>
15
))
/
chL
;
}
chest_mag
=
max
(
chest_mag
,(
chest0_re
[
aa
][
re
]
*
chest0_re
[
aa
][
re
])
+
(
chest0_im
[
aa
][
re
]
*
chest0_im
[
aa
][
re
]));
chest_mag
=
max
(
chest_mag
,(
chest1_re
[
aa
][
re
]
*
chest1_re
[
aa
][
re
])
+
(
chest1_im
[
aa
][
re
]
*
chest1_im
[
aa
][
re
]));
}
}
log2_maxh
=
log2_approx
(
chest_mag
)
/
2
;
#ifdef DEBUG_PUCCH_RX
printf
(
"[eNB] PUCCH subframe %d l %d re %d chest1 => (%d,%d)
\n
"
,
subframe
,
l
,
re
,
chest_re
,
chest_im
);
printf
(
"PUCCH 1A: log2_maxh %d
\n
"
,
log2_maxh
);
#endif
// now do channel matched filter
for
(
aa
=
0
;
aa
<
frame_parms
->
nb_antennas_rx
;
aa
++
)
{
for
(
re
=
0
;
re
<
12
;
re
++
)
{
#ifdef DEBUG_PUCCH_RX
printf
(
"[eNB] PUCCH subframe %d chest0[%d][%d] => (%d,%d)
\n
"
,
subframe
,
aa
,
re
,
chest0_re
[
aa
][
re
],
chest0_im
[
aa
][
re
]);
#endif
// first slot, left of RS
for
(
l
=
0
;
l
<
2
;
l
++
)
{
off
=
(
re
<<
1
)
+
(
24
*
l
);
tmp_re
=
((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
l
<<
1
])
>>
15
)
-
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
);
tmp_im
=
((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
)
+
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[(
l
<<
1
)])
>>
15
);
stat_re
+=
(((
tmp_re
*
chest
_re
)
>>
15
)
+
((
tmp_im
*
chest_im
)
>>
15
))
/
4
;
stat_im
+=
(((
tmp_re
*
chest
_im
)
>>
15
)
-
((
tmp_im
*
chest_re
)
>>
15
))
/
4
;
stat_re
+=
(((
tmp_re
*
chest
0_re
[
aa
][
re
])
>>
log2_maxh
)
+
((
tmp_im
*
chest0_im
[
aa
][
re
])
>>
log2_maxh
))
;
stat_im
+=
(((
tmp_re
*
chest
0_im
[
aa
][
re
])
>>
log2_maxh
)
-
((
tmp_im
*
chest0_re
[
aa
][
re
])
>>
log2_maxh
))
;
off
+=
2
;
#ifdef DEBUG_PUCCH_RX
printf
(
"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)
\n
"
,
subframe
,
l
,
re
,
rxcomp
[
aa
][
off
],
rxcomp
[
aa
][
1
+
off
],
cfo
[
l
<<
1
],
cfo
[
1
+
(
l
<<
1
)],
stat_re
,
stat_im
);
printf
(
"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) => (%d,%d)
\n
"
,
subframe
,
l
,
re
,
rxcomp
[
aa
][
off
],
rxcomp
[
aa
][
1
+
off
],
cfo
[
l
<<
1
],
cfo
[
1
+
(
l
<<
1
)],
tmp_re
,
tmp_im
,
stat_re
,
stat_im
);
#endif
}
}
// first slot, right of RS
for
(
l
=
(
nsymb
>>
1
)
-
2
;
l
<
(
nsymb
>>
1
);
l
++
)
{
off
=
(
re
<<
1
)
+
(
24
*
l
);
tmp_re
=
((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
l
<<
1
])
>>
15
)
-
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
);
tmp_im
=
((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
)
+
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[(
l
<<
1
)])
>>
15
);
stat_re
+=
(((
tmp_re
*
chest
_re
)
>>
15
)
+
((
tmp_im
*
chest_im
)
>>
15
))
/
4
;
stat_im
+=
(((
tmp_re
*
chest
_im
)
>>
15
)
-
((
tmp_im
*
chest_re
)
>>
15
))
/
4
;
stat_re
+=
(((
tmp_re
*
chest
0_re
[
aa
][
re
])
>>
log2_maxh
)
+
((
tmp_im
*
chest0_im
[
aa
][
re
])
>>
log2_maxh
))
;
stat_im
+=
(((
tmp_re
*
chest
0_im
[
aa
][
re
])
>>
log2_maxh
)
-
((
tmp_im
*
chest0_re
[
aa
][
re
])
>>
log2_maxh
))
;
off
+=
2
;
#ifdef DEBUG_PUCCH_RX
printf
(
"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)
\n
"
,
subframe
,
l
,
re
,
rxcomp
[
aa
][
off
],
rxcomp
[
aa
][
1
+
off
],
cfo
[
l
<<
1
],
cfo
[
1
+
(
l
<<
1
)],
stat_re
,
stat_im
);
printf
(
"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) => (%d,%d)
\n
"
,
subframe
,
l
,
re
,
rxcomp
[
aa
][
off
],
rxcomp
[
aa
][
1
+
off
],
cfo
[
l
<<
1
],
cfo
[
1
+
(
l
<<
1
)],
tmp_re
,
tmp_im
,
stat_re
,
stat_im
);
#endif
}
chest_re
=
0
;
chest_im
=
0
;
// channel estimate for second slot
for
(
l
=
2
;
l
<
(
nsymb
>>
1
)
-
2
;
l
++
)
{
off
=
(
re
<<
1
)
+
(
24
*
l
)
+
(
nsymb
>>
1
)
*
24
;
chest_re
+=
(((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
l
<<
1
])
>>
15
)
-
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
))
/
chL
;
chest_im
+=
(((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
)
+
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[(
l
<<
1
)])
>>
15
))
/
chL
;
}
}
#ifdef DEBUG_PUCCH_RX
printf
(
"[eNB] PUCCH subframe %d
l %d re %d chest2 => (%d,%d)
\n
"
,
subframe
,
l
,
re
,
chest
_re
,
chest_im
);
printf
(
"[eNB] PUCCH subframe %d
chest1[%d][%d] => (%d,%d)
\n
"
,
subframe
,
aa
,
re
,
chest
0_re
[
aa
][
re
],
chest0_im
[
aa
][
re
]
);
#endif
// second slot, left of RS
for
(
l
=
0
;
l
<
2
;
l
++
)
{
off
=
(
re
<<
1
)
+
(
24
*
l
)
+
(
nsymb
>>
1
)
*
24
;
tmp_re
=
((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
l
<<
1
])
>>
15
)
-
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
);
tmp_im
=
((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
)
+
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[(
l
<<
1
)])
>>
15
);
stat_re
+=
(((
tmp_re
*
chest_re
)
>>
15
)
+
((
tmp_im
*
chest_im
)
>>
15
))
/
4
;
stat_im
+=
(((
tmp_re
*
chest
_im
)
>>
15
)
-
((
tmp_im
*
chest_re
)
>>
15
))
/
4
;
off
=
(
re
<<
1
)
+
(
24
*
l
)
+
(
nsymb
>>
1
)
*
24
;
tmp_re
=
((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
l
<<
1
])
>>
15
)
-
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
);
tmp_im
=
((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
)
+
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[(
l
<<
1
)])
>>
15
);
stat_re
+=
(((
tmp_re
*
chest1_re
[
aa
][
re
])
>>
log2_maxh
)
+
((
tmp_im
*
chest1_im
[
aa
][
re
])
>>
log2_maxh
))
;
stat_im
+=
(((
tmp_re
*
chest
1_im
[
aa
][
re
])
>>
log2_maxh
)
-
((
tmp_im
*
chest1_re
[
aa
][
re
])
>>
log2_maxh
))
;
off
+=
2
;
#ifdef DEBUG_PUCCH_RX
printf
(
"[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)
\n
"
,
subframe
,
l
,
re
,
rxcomp
[
aa
][
off
],
rxcomp
[
aa
][
1
+
off
],
cfo
[
l
<<
1
],
cfo
[
1
+
(
l
<<
1
)],
stat_re
,
stat_im
);
printf
(
"[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) => (%d,%d)
\n
"
,
subframe
,
l
,
re
,
rxcomp
[
aa
][
off
],
rxcomp
[
aa
][
1
+
off
],
cfo
[
l
<<
1
],
cfo
[
1
+
(
l
<<
1
)],
tmp_re
,
tmp_im
,
stat_re
,
stat_im
);
#endif
}
// second slot, right of RS
for
(
l
=
(
nsymb
>>
1
)
-
2
;
l
<
(
nsymb
>>
1
)
-
1
;
l
++
)
{
off
=
(
re
<<
1
)
+
(
24
*
l
)
+
(
nsymb
>>
1
)
*
24
;
tmp_re
=
((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
l
<<
1
])
>>
15
)
-
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
);
tmp_im
=
((
rxcomp
[
aa
][
off
]
*
(
int32_t
)
cfo
[
1
+
(
l
<<
1
)])
>>
15
)
+
((
rxcomp
[
aa
][
1
+
off
]
*
(
int32_t
)
cfo
[(
l
<<
1
)])
>>
15
);
stat_re
+=
(((
tmp_re
*
chest
_re
)
>>
15
)
+
((
tmp_im
*
chest_im
)
>>
15
))
/
4
;
stat_im
+=
(((
tmp_re
*
chest
_im
)
>>
15
)
-
((
tmp_im
*
chest_re
)
>>
15
))
/
4
;
stat_re
+=
(((
tmp_re
*
chest
1_re
[
aa
][
re
])
>>
log2_maxh
)
+
((
tmp_im
*
chest1_im
[
aa
][
re
])
>>
log2_maxh
))
;
stat_im
+=
(((
tmp_re
*
chest
1_im
[
aa
][
re
])
>>
log2_maxh
)
-
((
tmp_im
*
chest1_re
[
aa
][
re
])
>>
log2_maxh
))
;
off
+=
2
;
#ifdef DEBUG_PUCCH_RX
printf
(
"[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)
\n
"
,
subframe
,
l
,
re
,
rxcomp
[
aa
][
off
],
rxcomp
[
aa
][
1
+
off
],
cfo
[
l
<<
1
],
cfo
[
1
+
(
l
<<
1
)],
stat_re
,
stat_im
);
printf
(
"[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) => (%d,%d)
\n
"
,
subframe
,
l
,
re
,
rxcomp
[
aa
][
off
],
rxcomp
[
aa
][
1
+
off
],
cfo
[
l
<<
1
],
cfo
[
1
+
(
l
<<
1
)],
tmp_re
,
tmp_im
,
stat_re
,
stat_im
);
#endif
}
...
...
@@ -2392,7 +2426,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
LOG_I
(
PHY
,
"PUCCH 1a/b: subframe %d : stat %d,%d (pos %d)
\n
"
,
subframe
,
stat_re
,
stat_im
,
(
subframe
<<
10
)
+
(
eNB
->
pucch1ab_stats_cnt
[
UE_id
][
subframe
]));
LOG_I
(
PHY
,
"PUCCH 1a/b: subframe %d : sigma2_dB %d, stat_max %d, pucch1_thres %d
\n
"
,
subframe
,
sigma2_dB
,
dB_fixed
(
stat_max
),
pucch1_thres
);
eNB
->
pucch1ab_stats
[
UE_id
][(
subframe
<<
11
)
+
2
*
(
eNB
->
pucch1ab_stats_cnt
[
UE_id
][
subframe
])]
=
(
stat_re
);
eNB
->
pucch1ab_stats
[
UE_id
][(
subframe
<<
11
)
+
1
+
2
*
(
eNB
->
pucch1ab_stats_cnt
[
UE_id
][
subframe
])]
=
(
stat_im
);
...
...
openair2/LAYER2/MAC/eNB_scheduler_RA.c
View file @
3197c314
...
...
@@ -1118,7 +1118,7 @@ void check_Msg4_retransmission(module_id_t module_idP,int CC_idP,frame_t frameP,
}
// Msg4 frame/subframe
}
// regular LTE case
}
else
{
LOG_
D
(
MAC
,
"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged
\n
"
,
module_idP
,
CC_idP
,
frameP
,
subframeP
);
LOG_
I
(
MAC
,
"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged
\n
"
,
module_idP
,
CC_idP
,
frameP
,
subframeP
);
RA_template
->
wait_ack_Msg4
=
0
;
RA_template
->
RA_active
=
FALSE
;
UE_id
=
find_UE_id
(
module_idP
,
RA_template
->
rnti
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment