From 92dc641e98bc12f6e2a2e8326c9c930d27ae4bb6 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 19 Aug 2025 09:17:33 +0200 Subject: [PATCH 1/6] common channel level function --- .../PHY/nr_phy_common/inc/nr_phy_common.h | 7 ++++++ .../PHY/nr_phy_common/src/nr_phy_common.c | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index d52b6d9c43..febf434e5a 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -54,6 +54,13 @@ void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_si void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay); unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb); void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, const c16_t *rxdata_in, c16_t *rxdata_out, int size); +void nr_channel_level(const int symbol, + const int size_est, + const c16_t ch_estimates_ext[][size_est], + const int nb_rx, + const int Nl, + int32_t avg[nb_rx * Nl], + const uint32_t len); void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, const csi_mapping_parms_t *phy_csi_parms, const int16_t amp, diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common.c b/openair1/PHY/nr_phy_common/src/nr_phy_common.c index e86652bd49..4e8951d124 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common.c @@ -420,6 +420,28 @@ unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, in return (0); } +// compute average channel_level on each antenna +void nr_channel_level(const int symbol, + const int size_est, + const c16_t ch_estimates_ext[][size_est], + const int nb_rx, + const int Nl, + int32_t avg[nb_rx * Nl], + const uint32_t len) +{ + int16_t x = factor2(len); + int16_t y = len >> x; + for (int aarx = 0; aarx < nb_rx; aarx++) { + for (int l = 0; l < Nl; l++) { + simde__m128i *ch128 = (simde__m128i *)&ch_estimates_ext[l * nb_rx + aarx][symbol * len]; + //compute average level + avg[l * nb_rx + aarx] = simde_mm_average(ch128, len, x, y); + LOG_D(PHY, "Channel level: %d\n", avg[l * nb_rx + aarx]); + } + } +} + + void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, const c16_t *rxdata_in, c16_t *rxdata_out, int size) { const double phase_inc = -fo_Hz / (samples_per_ms * 1000); From a95a32c2f63ea70df75fb5212b13db409ff625e6 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 19 Aug 2025 09:32:19 +0200 Subject: [PATCH 2/6] use common channel level for PBCH --- openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c | 38 ++++--------------- openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c | 8 +++- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 3 -- 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 298de612ee..8065da24b2 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -38,6 +38,7 @@ #include #include #include "openair1/PHY/NR_REFSIG/nr_refsig_common.h" +#include "PHY/nr_phy_common/inc/nr_phy_common.h" #include "instrumentation.h" //#define DEBUG_PBCH //#define DEBUG_PBCH_ENCODING @@ -201,31 +202,6 @@ static uint16_t nr_pbch_extract(uint32_t rxdataF_sz, return(0); } -//__m128i avg128; - -//compute average channel_level on each (TX,RX) antenna pair -int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], - const NR_DL_FRAME_PARMS *frame_parms, - int nb_re) -{ - int32_t avg2 = 0; - - for (int aarx=0; aarxnb_antennas_rx; aarx++) { - - simde__m128i *dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[aarx]; - - //compute average level - int32_t avg1 = simde_mm_average(dl_ch128, nb_re, 0, nb_re); - - if (avg1>avg2) - avg2 = avg1; - - //LOG_I(PHY,"Channel level : %d, %d\n",avg1, avg2); - } - - return(avg2); -} - void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL], struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], int nb_re, @@ -346,7 +322,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, const struct complex16 rxdataF[][rxdataFSize]) { TracyCZone(ctx, true); - int max_h=0; int symbol; uint8_t Lmax=frame_parms->Lmax; int M = NR_POLAR_PBCH_E; @@ -390,11 +365,14 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, LOG_I(PHY,"[PHY] PBCH starting channel_level\n"); #endif + int max_h = 0; if (symbol == 1) { - max_h = nr_pbch_channel_level(dl_ch_estimates_ext, - frame_parms, - nb_re); - log2_maxh = 3+(log2_approx(max_h)/2); + int avg[frame_parms->nb_antennas_rx]; + nr_channel_level(0, PBCH_MAX_RE_PER_SYMBOL, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, 1, avg, nb_re); + max_h = avg[0]; + for (int i = 1; i < frame_parms->nb_antennas_rx; i++) + max_h = cmax(avg[i], max_h); + log2_maxh = 3 + (log2_approx(max_h) / 2); } #ifdef DEBUG_PBCH diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c b/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c index 7406855cc4..1010a6e5e8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_psbch_rx.c @@ -25,6 +25,7 @@ #include "common/utils/LOG/log.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "PHY/TOOLS/phy_scope_interface.h" +#include "PHY/nr_phy_common/inc/nr_phy_common.h" // #define DEBUG_PSBCH @@ -158,8 +159,11 @@ int nr_rx_psbch(PHY_VARS_NR_UE *ue, int max_h = 0; if (symbol == 0) { - max_h = nr_pbch_channel_level(dl_ch_estimates_ext, frame_parms, nb_re); - // log2_maxh = 3+(log2_approx(max_h)/2); + int avg[frame_parms->nb_antennas_rx]; + nr_channel_level(0, PBCH_MAX_RE_PER_SYMBOL, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, 1, avg, nb_re); + max_h = avg[0]; + for (int i = 1; i < frame_parms->nb_antennas_rx; i++) + max_h = cmax(avg[i], max_h); log2_maxh = 5 + (log2_approx(max_h) / 2); // LLR32 crc error. LLR 16 CRC works } #ifdef DEBUG_PSBCH diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index a4098394ac..395081b4a8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -346,9 +346,6 @@ void nr_tx_psbch(PHY_VARS_NR_UE *UE, uint32_t frame_tx, uint32_t slot_tx, sl_nr_ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, int num_frames); // Reuse already existing PBCH functions -int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], - const NR_DL_FRAME_PARMS *frame_parms, - int nb_re); void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL], struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], int nb_re, From 65d0fb152e4a9b89b1101ec449bbbde1d55abad2 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 19 Aug 2025 10:00:00 +0200 Subject: [PATCH 3/6] use common channel level for DCI reception --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index b4e2c413cf..43b27e3932 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -36,6 +36,7 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h" #include "PHY/phy_extern.h" #include "PHY/CODING/coding_extern.h" +#include "PHY/nr_phy_common/inc/nr_phy_common.h" #include "PHY/sse_intrin.h" #include "common/utils/nr/nr_common.h" #include @@ -197,20 +198,6 @@ static void nr_pdcch_llr(uint32_t sz, c16_t *rxF, c16_t *llr) } } -//compute average channel_level on each (TX,RX) antenna pair -static int32_t nr_pdcch_channel_level(int nb_re, int arraySz, c16_t dl_ch_estimates_ext[][arraySz], int nb_antennas_rx) -{ - int32_t avgs = 0; - for (int aarx = 0; aarx < nb_antennas_rx; aarx++) { - simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx]; - // compute average level - // if nb_re is not %4, some samples are missed inside simde_mm_average, so let's discard it - int32_t tmp = simde_mm_average(dl_ch128, nb_re & ~3, 0, nb_re & ~3); - avgs = cmax(avgs, tmp); - } - return avgs; -} - // This function will extract the mapped DM-RS PDCCH REs as per 38.211 Section 7.4.1.3.2 (Mapping to physical resources) static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, uint32_t coreset_nbr_rb, @@ -372,9 +359,13 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, rel15->coreset.frequency_domain_resource, rel15->BWPStart); - LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); + LOG_D(NR_PHY_DCI, "in channel level function (dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); // compute channel level based on ofdm symbol 0 - int32_t avgs = nr_pdcch_channel_level(n_rb, arraySz, pdcch_dl_ch_estimates_ext, antRx); + int avg[antRx]; + nr_channel_level(0, arraySz, pdcch_dl_ch_estimates_ext, antRx, 1, avg, n_rb); + int avgs = avg[0]; + for (int i = 1; i < antRx; i++) + avgs = cmax(avgs, avg[i]); uint8_t log2_maxh = (log2_approx(avgs) / 2) + 5; //+antRx; #ifdef UE_DEBUG_TRACE From 8d904dbf233f2ba29576a3a8c4ce2104b4dce471 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 19 Aug 2025 10:17:51 +0200 Subject: [PATCH 4/6] use common channel level for PUSCH --- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 46 +++++-------------- 1 file changed, 11 insertions(+), 35 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index e8d8efeb28..bd4ee92284 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -7,6 +7,7 @@ #include "PHY/NR_REFSIG/ptrs_nr.h" #include "PHY/NR_ESTIMATION/nr_ul_estimation.h" #include "PHY/defs_nr_common.h" +#include "PHY/nr_phy_common/inc/nr_phy_common.h" #include "common/utils/nr/nr_common.h" #include #include "PHY/sse_intrin.h" @@ -210,31 +211,6 @@ static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t } else return(rel15_ul->rb_size * NR_NB_SC_PER_RB); } -// compute average channel_level on each (TX,RX) antenna pair -static void nr_ulsch_channel_level(int size_est, - int ul_ch_estimates_ext[][size_est], - NR_DL_FRAME_PARMS *frame_parms, - int32_t *avg, - uint8_t symbol, - uint32_t len, - uint8_t nrOfLayers) -{ - int16_t x = factor2(len); - int16_t y = (len)>>x; - - for (int aatx = 0; aatx < nrOfLayers; aatx++) { - for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - - simde__m128i *ul_ch128 = (simde__m128i *)&ul_ch_estimates_ext[aatx * frame_parms->nb_antennas_rx + aarx][symbol * len]; - - //compute average level - avg[aatx * frame_parms->nb_antennas_rx + aarx] = simde_mm_average(ul_ch128, len, x, y); - //LOG_D(PHY, "Channel level: %d\n", avg[aatx * frame_parms->nb_antennas_rx + aarx]); - } - } - -} - static void nr_ulsch_channel_compensation(uint32_t buffer_length, int nb_rx_ant, c16_t rxFext[][buffer_length], @@ -1394,8 +1370,6 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, rel15_ul, frame_parms); - int avgs = 0; - int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; uint8_t shift_ch_ext = rel15_ul->nrOfLayers > 1 ? log2_approx(max_ch >> 11) : 0; //---------------------------------------------------------- @@ -1410,15 +1384,17 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, rel15_ul->nrOfLayers, rel15_ul->rb_size, shift_ch_ext); - - nr_ulsch_channel_level(size_est, - ul_ch_estimates_ext, - frame_parms, - avg, - meas_symbol, // index of the start symbol - nb_re_pusch, // number of the re in pusch - rel15_ul->nrOfLayers); + int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; + nr_channel_level(meas_symbol, + size_est, + (c16_t (*)[size_est])ul_ch_estimates_ext, + frame_parms->nb_antennas_rx, + rel15_ul->nrOfLayers, + avg, + nb_re_pusch); + + int avgs = 0; for (int nl = 0; nl < rel15_ul->nrOfLayers; nl++) for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) avgs = cmax(avgs, avg[nl * frame_parms->nb_antennas_rx + aarx]); From 6af8f5619a0513290cbab3a31263532ced0db6ca Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 19 Aug 2025 11:30:00 +0200 Subject: [PATCH 5/6] use common channel level for PDSCH --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 65 +++---------------- 1 file changed, 8 insertions(+), 57 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index d0457b3bb9..39f91d3b4e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -193,20 +193,6 @@ static void nr_dlsch_channel_compensation(uint32_t rx_size_symbol, unsigned char output_shift, PHY_NR_MEASUREMENTS *measurements); -/** \brief This function computes the average channel level over all allocated RBs and antennas (TX/RX) in order to compute output shift for compensated signal - @param dl_ch_estimates_ext Channel estimates in allocated RBs - @param frame_parms Pointer to frame descriptor - @param avg Pointer to average signal strength - @param pilots_flag Flag to indicate pilots in symbol - @param nb_rb Number of allocated RBs -*/ -static void nr_dlsch_channel_level(uint32_t rx_size_symbol, - int32_t dl_ch_estimates_ext[][rx_size_symbol], - uint8_t n_rx, - uint8_t n_tx, - int32_t avg[MAX_ANT][MAX_ANT], - uint32_t len); - void nr_dlsch_scale_channel(uint32_t rx_size_symbol, int32_t dl_ch_estimates_ext[][rx_size_symbol], NR_DL_FRAME_PARMS *frame_parms, @@ -538,25 +524,25 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, //---------------------------------------------------------- start_meas_nr_ue_phy(ue, DLSCH_CHANNEL_LEVEL_STATS); if (first_symbol_flag) { - int32_t avg[MAX_ANT][MAX_ANT] = {}; + int32_t avg[nl * n_rx]; if (nb_re_pdsch) - nr_dlsch_channel_level(rx_size_symbol, dl_ch_estimates_ext, frame_parms->nb_antennas_rx, nl, avg, nb_re_pdsch); + nr_channel_level(0, rx_size_symbol, (c16_t (*)[rx_size_symbol])dl_ch_estimates_ext, n_rx, nl, avg, nb_re_pdsch); else LOG_E(NR_PHY, "Average channel level is 0: nb_rb_pdsch = %d, nb_re_pdsch = %d\n", nb_rb_pdsch, nb_re_pdsch); int avgs = 0; int32_t median[MAX_ANT][MAX_ANT]; - for (int aatx = 0; aatx < nl; aatx++) + for (int l = 0; l < nl; l++) for (int aarx = 0; aarx < n_rx; aarx++) { - avgs = cmax(avgs, avg[aatx][aarx]); - LOG_D(PHY, "nb_rb %d avg_%d_%d Power per SC is %d\n", nb_rb_pdsch, aarx, aatx, avg[aatx][aarx]); + avgs = cmax(avgs, avg[l * n_rx + aarx]); + LOG_D(PHY, "nb_rb %d avg_%d_%d Power per SC is %d\n", nb_rb_pdsch, aarx, l, avg[l * n_rx + aarx]); LOG_D(PHY, "avgs Power per SC is %d\n", avgs); - median[aatx][aarx] = avg[aatx][aarx]; + median[l][aarx] = avg[l * n_rx + aarx]; } if (nl > 1) { nr_dlsch_channel_level_median(rx_size_symbol, dl_ch_estimates_ext, median, nl, n_rx, nb_re_pdsch); - for (int aatx = 0; aatx < nl; aatx++) { + for (int l = 0; l < nl; l++) { for (int aarx = 0; aarx < n_rx; aarx++) { - avgs = cmax(avgs, median[aatx][aarx]); + avgs = cmax(avgs, median[l][aarx]); } } } @@ -1032,41 +1018,6 @@ void nr_dlsch_scale_channel(uint32_t rx_size_symbol, } } - -/** @brief This function computes the average channel level over all allocated RBs - * and antennas (TX/RX) in order to compute output shift for compensated signal - @param rx_size_symbol - @param dl_ch_estimates_ext Channel estimates in allocated RBs - @param n_rx number of antennas in RX - @param n_tx number of antennas in TX - @param avg Pointer to average signal strength - @param len Number of allocated PDSCH REs -*/ -void nr_dlsch_channel_level(uint32_t rx_size_symbol, - int32_t dl_ch_estimates_ext[][rx_size_symbol], - uint8_t n_rx, - uint8_t n_tx, - int32_t avg[MAX_ANT][MAX_ANT], - uint32_t len) -{ - int16_t x = factor2(len); - int16_t y = (len) >> x; - - uint32_t nb_rb_0 = len / NR_NB_SC_PER_RB + ((len % NR_NB_SC_PER_RB) ? 1 : 0); - LOG_D(NR_PHY, "nb_rb_0 %d len %d = %d * 2^(%d)\n", nb_rb_0, len, y, x); - - for (int aatx = 0; aatx < n_tx; aatx++) { - for (int aarx = 0; aarx < n_rx; aarx++) { - - simde__m128i *dl_ch128 = (simde__m128i *)dl_ch_estimates_ext[(aatx * n_rx) + aarx]; - - //compute average level - avg[aatx][aarx] = simde_mm_average(dl_ch128, nb_rb_0 * 12, x, y); - //LOG_D(PHY, "Channel level: %d\n", avg[aatx][aarx]); - } - } -} - static void nr_dlsch_channel_level_median(uint32_t rx_size_symbol, int32_t dl_ch_estimates_ext[][rx_size_symbol], int32_t median[MAX_ANT][MAX_ANT], From b4796b4ddae0137da6d6535f07b288c50b86022f Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 15 Oct 2024 08:22:35 +0200 Subject: [PATCH 6/6] remove unused deinterleaving function from dlsch ue --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 47 ------------------- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 7 --- 2 files changed, 54 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 39f91d3b4e..1da2ef8d45 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -781,53 +781,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, return (0); } -void nr_dlsch_deinterleaving(uint8_t symbol, - uint8_t start_symbol, - uint16_t L, - uint16_t *llr, - uint16_t *llr_deint, - uint16_t nb_rb_pdsch) -{ - - uint32_t bundle_idx, N_bundle, R, C, r,c; - int32_t m,k; - uint8_t nb_re; - - R=2; - N_bundle = nb_rb_pdsch/L; - C=N_bundle/R; - - uint32_t bundle_deint[N_bundle]; - memset(bundle_deint, 0 , sizeof(bundle_deint)); - - printf("N_bundle %u L %d nb_rb_pdsch %d\n",N_bundle, L,nb_rb_pdsch); - - if (symbol==start_symbol) - nb_re = 6; - else - nb_re = 12; - - - AssertFatal(llr!=NULL,"nr_dlsch_deinterleaving: FATAL llr is Null\n"); - - - for (c =0; c< C; c++){ - for (r=0; r