Add pseudo-random bit sequence generator to libosmcoore

These PRBS sequences are specified in ITU-T O.150.  They are typically
used as test data to be transmitted for BER (bit error rate) testing.

Change-Id: I227b6a6e86a251460ecb816afa9a7439d5fb94d1
This commit is contained in:
Harald Welte 2017-06-18 18:16:02 +03:00
parent 548e371200
commit 1389e86d11
8 changed files with 175 additions and 3 deletions

View File

@ -31,6 +31,7 @@ nobase_include_HEADERS = \
osmocom/core/macaddr.h \
osmocom/core/msgb.h \
osmocom/core/panic.h \
osmocom/core/prbs.h \
osmocom/core/prim.h \
osmocom/core/process.h \
osmocom/core/rate_ctr.h \

View File

@ -0,0 +1,25 @@
#pragma once
#include <stdint.h>
#include <osmocom/core/bits.h>
/*! \brief definition of a PRBS sequence */
struct osmo_prbs {
const char *name; /*!< human-readable name */
unsigned int len; /*!< length in bits */
uint64_t coeff; /*!< coefficients */
};
/*! \brief state of a given PRBS sequence generator */
struct osmo_prbs_state {
const struct osmo_prbs *prbs;
uint64_t state;
};
extern const struct osmo_prbs osmo_prbs7;
extern const struct osmo_prbs osmo_prbs9;
extern const struct osmo_prbs osmo_prbs11;
extern const struct osmo_prbs osmo_prbs15;
void osmo_prbs_state_init(struct osmo_prbs_state *st, const struct osmo_prbs *prbs);
ubit_t osmo_prbs_get_ubit(struct osmo_prbs_state *state);
int osmo_prbs_get_ubits(ubit_t *out, unsigned int out_len, struct osmo_prbs_state *state);

View File

@ -21,7 +21,7 @@ libosmocore_la_SOURCES = timer.c timer_gettimeofday.c select.c signal.c msgb.c b
conv.c application.c rbtree.c strrb.c \
loggingrb.c crc8gen.c crc16gen.c crc32gen.c crc64gen.c \
macaddr.c stat_item.c stats.c stats_statsd.c prim.c \
conv_acc.c conv_acc_generic.c sercomm.c
conv_acc.c conv_acc_generic.c sercomm.c prbs.c
if HAVE_SSE3
libosmocore_la_SOURCES += conv_acc_sse.c

74
src/prbs.c Normal file
View File

@ -0,0 +1,74 @@
/* Osmocom implementation of pseudo-random bit sequence generation */
/* (C) 2017 by Harald Welte <laforge@gnumonks.org> */
#include <stdint.h>
#include <string.h>
#include <osmocom/core/bits.h>
#include <osmocom/core/prbs.h>
/*! \brief PRBS-7 according ITU-T O.150 */
const struct osmo_prbs osmo_prbs7 = {
/* x^7 + x^6 + 1 */
.name = "PRBS-7",
.len = 7,
.coeff = (1<<6) | (1<<5),
};
/*! \brief PRBS-9 according ITU-T O.150 */
const struct osmo_prbs osmo_prbs9 = {
/* x^9 + x^5 + 1 */
.name = "PRBS-9",
.len = 9,
.coeff = (1<<8) | (1<<4),
};
/*! \brief PRBS-11 according ITU-T O.150 */
const struct osmo_prbs osmo_prbs11 = {
/* x^11 + x^9 + 1 */
.name = "PRBS-11",
.len = 11,
.coeff = (1<<10) | (1<<8),
};
/*! \brief PRBS-15 according ITU-T O.150 */
const struct osmo_prbs osmo_prbs15 = {
/* x^15 + x^14+ 1 */
.name = "PRBS-15",
.len = 15,
.coeff = (1<<14) | (1<<13),
};
/*! \brief Initialize the given caller-allocated PRBS state */
void osmo_prbs_state_init(struct osmo_prbs_state *st, const struct osmo_prbs *prbs)
{
memset(st, 0, sizeof(*st));
st->prbs = prbs;
st->state = 1;
}
static void osmo_prbs_process_bit(struct osmo_prbs_state *state, ubit_t bit)
{
state->state >>= 1;
if (bit)
state->state ^= state->prbs->coeff;
}
/*! \brief Get the next bit out of given PRBS instance */
ubit_t osmo_prbs_get_ubit(struct osmo_prbs_state *state)
{
ubit_t result = state->state & 0x1;
osmo_prbs_process_bit(state, result);
return result;
}
/*! \brief Fill buffer of unpacked bits with next bits out of given PRBS instance */
int osmo_prbs_get_ubits(ubit_t *out, unsigned int out_len, struct osmo_prbs_state *state)
{
unsigned int i;
for (i = 0; i < out_len; i++)
out[i] = osmo_prbs_get_ubit(state);
return i;
}

View File

@ -15,7 +15,7 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \
write_queue/wqueue_test socket/socket_test \
coding/coding_test conv/conv_gsm0503_test \
abis/abis_test endian/endian_test sercomm/sercomm_test \
stats/stats_test
stats/stats_test prbs/prbs_test
if ENABLE_MSGFILE
check_PROGRAMS += msgfile/msgfile_test
@ -183,6 +183,9 @@ endian_endian_test_LDADD = $(top_builddir)/src/libosmocore.la
sercomm_sercomm_test_SOURCES = sercomm/sercomm_test.c
sercomm_sercomm_test_LDADD = $(top_builddir)/src/libosmocore.la
prbs_prbs_test_SOURCES = prbs/prbs_test.c
prbs_prbs_test_LDADD = $(top_builddir)/src/libosmocore.la
# The `:;' works around a Bash 3.2 bug when the output is not writeable.
$(srcdir)/package.m4: $(top_srcdir)/configure.ac
:;{ \
@ -226,7 +229,7 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
osmo-auc-gen/osmo-auc-gen_test.ok \
osmo-auc-gen/osmo-auc-gen_test.err \
conv/conv_gsm0503_test.ok endian/endian_test.ok \
sercomm/sercomm_test.ok
sercomm/sercomm_test.ok prbs/prbs_test.ok
DISTCLEANFILES = atconfig atlocal conv/gsm0503_test_vectors.c
BUILT_SOURCES = conv/gsm0503_test_vectors.c

47
tests/prbs/prbs_test.c Normal file
View File

@ -0,0 +1,47 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <osmocom/core/prbs.h>
static void dump_bits(const ubit_t *bits, unsigned int num_bits)
{
unsigned int i;
for (i = 0; i < num_bits; i++) {
if (bits[i])
fputc('1', stdout);
else
fputc('0', stdout);
}
fputc('\n',stdout);
}
static void test_prbs(const struct osmo_prbs *prbs)
{
struct osmo_prbs_state st;
unsigned int i;
printf("Testing PRBS sequence generation '%s'\n", prbs->name);
osmo_prbs_state_init(&st, prbs);
/* 2 lines */
for (i = 0; i < 2; i++) {
unsigned int seq_len = (1 << prbs->len)-1;
ubit_t bits[seq_len];
memset(bits, 0, sizeof(bits));
osmo_prbs_get_ubits(bits, sizeof(bits), &st);
dump_bits(bits, sizeof(bits));
}
printf("\n");
}
int main(int argc, char **argv)
{
test_prbs(&osmo_prbs7);
test_prbs(&osmo_prbs9);
test_prbs(&osmo_prbs11);
test_prbs(&osmo_prbs15);
exit(0);
}

16
tests/prbs/prbs_test.ok Normal file

File diff suppressed because one or more lines are too long

View File

@ -280,3 +280,9 @@ AT_KEYWORDS([sercomm])
cat $abs_srcdir/sercomm/sercomm_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/sercomm/sercomm_test], [0], [expout], [ignore])
AT_CLEANUP
AT_SETUP([prbs])
AT_KEYWORDS([prbs])
cat $abs_srcdir/prbs/prbs_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/prbs/prbs_test], [0], [expout], [ignore])
AT_CLEANUP