srsLTE/srslte/lib/scrambling/src/scrambling.c

163 lines
4.3 KiB
C
Raw Normal View History

/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
2014-01-28 03:41:17 -08:00
*
* This file is part of the libLTE library.
2014-01-28 03:41:17 -08:00
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
2014-01-28 03:41:17 -08:00
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
2014-01-28 03:41:17 -08:00
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "srslte/scrambling/scrambling.h"
2014-01-28 03:41:17 -08:00
2015-03-18 08:05:38 -07:00
void scrambling_f(srslte_sequence_t *s, float *data) {
2014-06-17 02:11:41 -07:00
scrambling_f_offset(s, data, 0, s->len);
2014-01-28 03:41:17 -08:00
}
2015-03-18 08:05:38 -07:00
void scrambling_f_offset(srslte_sequence_t *s, float *data, int offset, int len) {
int i;
2014-06-17 02:11:41 -07:00
assert (len + offset <= s->len);
2014-06-17 02:11:41 -07:00
for (i = 0; i < len; i++) {
2014-06-17 07:32:19 -07:00
data[i] = data[i] * (1 - 2 * s->c[i + offset]);
2014-06-17 02:11:41 -07:00
}
2014-01-28 03:41:17 -08:00
}
2015-03-18 08:05:38 -07:00
void scrambling_c(srslte_sequence_t *s, cf_t *data) {
2014-06-17 02:11:41 -07:00
scrambling_c_offset(s, data, 0, s->len);
2014-03-27 09:31:25 -07:00
}
2015-03-18 08:05:38 -07:00
void scrambling_c_offset(srslte_sequence_t *s, cf_t *data, int offset, int len) {
2014-06-17 02:11:41 -07:00
int i;
assert (len + offset <= s->len);
2014-03-27 09:31:25 -07:00
2014-06-17 02:11:41 -07:00
for (i = 0; i < len; i++) {
2014-06-17 07:32:19 -07:00
data[i] = data[i] * (1 - 2 * s->c[i + offset]);
2014-06-17 02:11:41 -07:00
}
2014-03-27 09:31:25 -07:00
}
2015-03-18 08:05:38 -07:00
void scrambling_b(srslte_sequence_t *s, uint8_t *data) {
2014-06-17 02:11:41 -07:00
int i;
2014-01-28 03:41:17 -08:00
2014-06-17 02:11:41 -07:00
for (i = 0; i < s->len; i++) {
data[i] = (data[i] + s->c[i]) % 2;
}
2014-01-28 03:41:17 -08:00
}
2015-03-18 08:05:38 -07:00
void scrambling_b_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) {
2014-06-17 02:11:41 -07:00
int i;
assert (len + offset <= s->len);
for (i = 0; i < len; i++) {
2014-06-17 07:32:19 -07:00
data[i] = (data[i] + s->c[i + offset]) % 2;
2014-06-17 02:11:41 -07:00
}
}
/* As defined in 36.211 5.3.1 */
2015-03-18 08:05:38 -07:00
void scrambling_b_offset_pusch(srslte_sequence_t *s, uint8_t *data, int offset, int len) {
int i;
assert (len + offset <= s->len);
for (i = 0; i < len; i++) {
if (data[i] == 3) {
data[i] = 1;
} else if (data[i] == 2) {
if (i > 1) {
data[i] = data[i-1];
}
} else {
data[i] = (data[i] + s->c[i + offset]) % 2;
}
}
}
2014-01-28 03:41:17 -08:00
/** High-level API */
int compute_sequences(scrambling_hl* h) {
2014-06-17 02:11:41 -07:00
switch (h->init.channel) {
case SCRAMBLING_PBCH:
2015-03-18 08:05:38 -07:00
return srslte_sequence_pbch(&h->obj.seq[0],
2015-03-18 05:59:29 -07:00
h->init.nof_symbols == SRSLTE_SRSLTE_SRSLTE_CP_NORM_NSYMB ? SRSLTE_SRSLTE_CP_NORM : SRSLTE_SRSLTE_CP_EXT, h->init.cell_id);
2014-06-17 02:11:41 -07:00
case SCRAMBLING_PDSCH:
2015-03-18 05:41:50 -07:00
for (int ns = 0; ns < SRSLTE_NSUBFRAMES_X_FRAME; ns++) {
2015-03-18 08:05:38 -07:00
srslte_sequence_pdsch(&h->obj.seq[ns], h->init.nrnti, 0, 2 * ns, h->init.cell_id,
2015-03-18 05:59:29 -07:00
SRSLTE_NSOFT_BITS);
2014-06-17 07:32:19 -07:00
}
return 0;
2014-06-17 02:11:41 -07:00
case SCRAMBLING_PCFICH:
2015-03-18 05:41:50 -07:00
for (int ns = 0; ns < SRSLTE_NSUBFRAMES_X_FRAME; ns++) {
2015-03-18 08:05:38 -07:00
srslte_sequence_pcfich(&h->obj.seq[ns], 2 * ns, h->init.cell_id);
2014-06-17 02:11:41 -07:00
}
return 0;
case SCRAMBLING_PDCCH:
2015-03-18 05:41:50 -07:00
for (int ns = 0; ns < SRSLTE_NSUBFRAMES_X_FRAME; ns++) {
2015-03-18 08:05:38 -07:00
srslte_sequence_pdcch(&h->obj.seq[ns], 2 * ns, h->init.cell_id, SRSLTE_NSOFT_BITS);
2014-06-17 07:32:19 -07:00
}
return 0;
2014-06-17 02:11:41 -07:00
case SCRAMBLING_PMCH:
case SCRAMBLING_PUCCH:
fprintf(stderr, "Not implemented\n");
return -1;
default:
fprintf(stderr, "Invalid channel %d\n", h->init.channel);
return -1;
}
2014-01-28 03:41:17 -08:00
}
int scrambling_initialize(scrambling_hl* h) {
2014-06-17 02:11:41 -07:00
bzero(&h->obj, sizeof(scrambling_t));
2014-01-28 03:41:17 -08:00
2014-06-17 02:11:41 -07:00
return compute_sequences(h);
2014-01-28 03:41:17 -08:00
}
/** This function can be called in a subframe (1ms) basis for LTE */
int scrambling_work(scrambling_hl* hl) {
2014-06-17 02:11:41 -07:00
int sf;
if (hl->init.channel == SCRAMBLING_PBCH) {
sf = 0;
} else {
sf = hl->ctrl_in.subframe;
}
2015-03-18 08:05:38 -07:00
srslte_sequence_t *seq = &hl->obj.seq[sf];
2014-06-17 02:11:41 -07:00
if (hl->init.hard) {
2014-10-17 11:44:01 -07:00
memcpy(hl->output, hl->input, sizeof(uint8_t) * hl->in_len);
2014-06-17 02:11:41 -07:00
scrambling_b(seq, hl->output);
} else {
memcpy(hl->output, hl->input, sizeof(float) * hl->in_len);
scrambling_f(seq, hl->output);
}
hl->out_len = hl->in_len;
return 0;
2014-01-28 03:41:17 -08:00
}
int scrambling_stop(scrambling_hl* hl) {
2014-06-17 02:11:41 -07:00
int i;
2015-03-18 05:41:50 -07:00
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
2015-03-18 08:05:38 -07:00
srslte_sequence_free(&hl->obj.seq[i]);
2014-06-17 02:11:41 -07:00
}
return 0;
2014-01-28 03:41:17 -08:00
}