You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
3.8 KiB
C

/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* 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,
* 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/.
*
*/
#include <sys/time.h>
#include <stdlib.h>
#include <strings.h>
#include "liblte/phy/io/binsource.h"
#include "liblte/phy/utils/bit.h"
#define DIV(a,b) ((a-1)/b+1)
/* Internal functions */
static int gen_seq_buff(binsource_t* q, int nwords) {
if (q->seq_buff_nwords != nwords) {
free(q->seq_buff);
q->seq_buff_nwords = 0;
}
if (!q->seq_buff_nwords) {
q->seq_buff = malloc(nwords*sizeof(uint32_t));
if (!q->seq_buff) {
return -1;
}
q->seq_buff_nwords = nwords;
}
for (int i=0;i<q->seq_buff_nwords;i++) {
q->seq_buff[i] = rand_r(&q->seed);
}
return 0;
}
/* Low-level API */
/**
* Initializes the binsource object.
*/
void binsource_init(binsource_t* q) {
bzero((void*) q,sizeof(binsource_t));
}
/**
* Destroys binsource object
*/
void binsource_free(binsource_t* q) {
if (q->seq_buff) {
free(q->seq_buff);
}
bzero(q, sizeof(binsource_t));
}
/**
* Sets a new seed
*/
void binsource_seed_set(binsource_t* q, unsigned int seed) {
q->seed = seed;
}
/**
* Sets local time as seed.
*/
void binsource_seed_time(binsource_t *q) {
struct timeval t1;
gettimeofday(&t1, NULL);
q->seed = t1.tv_usec * t1.tv_sec;
}
/**
* Generates a sequence of nbits random bits
*/
int binsource_cache_gen(binsource_t* q, int nbits) {
if (gen_seq_buff(q,DIV(nbits,32))) {
return -1;
}
q->seq_cache_nbits = nbits;
q->seq_cache_rp = 0;
return 0;
}
static int int_2_bits(uint32_t* src, char* dst, int nbits) {
int n;
n=nbits/32;
for (int i=0;i<n;i++) {
bit_pack(src[i],&dst,32);
}
bit_pack(src[n],&dst,nbits-n*32);
return n;
}
/**
* Copies the next random bits to the buffer bits from the array generated by binsource_cache_gen
*/
void binsource_cache_cpy(binsource_t* q, char *bits, int nbits) {
q->seq_cache_rp += int_2_bits(&q->seq_buff[q->seq_cache_rp],bits,nbits);
}
/**
* Stores in the bits buffer a sequence of nbits pseudo-random bits.
* Overwrites the bits generated using binsource_cache_gen.
*/
int binsource_generate(binsource_t* q, char *bits, int nbits) {
if (gen_seq_buff(q,DIV(nbits,32))) {
return -1;
}
int_2_bits(q->seq_buff,bits,nbits);
return 0;
}
/* High-Level API */
int binsource_initialize(binsource_hl* hl) {
binsource_init(&hl->obj);
if (hl->init.seed) {
binsource_seed_set(&hl->obj,hl->init.seed);
} else {
binsource_seed_time(&hl->obj);
}
if (hl->init.cache_seq_nbits) {
if (binsource_cache_gen(&hl->obj,hl->init.cache_seq_nbits)) {
return -1;
}
}
return 0;
}
int binsource_work(binsource_hl* hl) {
int ret = -1;
if (hl->init.cache_seq_nbits) {
binsource_cache_cpy(&hl->obj,hl->output,hl->ctrl_in.nbits);
ret = 0;
} else {
ret = binsource_generate(&hl->obj,hl->output,hl->ctrl_in.nbits);
}
if (!ret) {
hl->out_len = hl->ctrl_in.nbits;
} else {
hl->out_len = 0;
}
return ret;
}
int binsource_stop(binsource_hl* hl) {
binsource_free(&hl->obj);
return 0;
}