hdlr_raw_prbs: More complete implementation, lifted from osmo-e1d/e1-prbs-gen
This commit is contained in:
parent
88e00cbc78
commit
e648c025ac
|
@ -1,2 +1,3 @@
|
||||||
*.o
|
*.o
|
||||||
|
*.a
|
||||||
capi-test
|
capi-test
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -7,12 +7,15 @@ CFLAGS += $(shell pkg-config --cflags talloc libosmocore capi20)
|
||||||
all: capi-test
|
all: capi-test
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -f *.o capi-test
|
@rm -f *.o prbs/*.o *.a capi-test
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) -o $@ -c $^
|
$(CC) $(CFLAGS) -o $@ -c $^
|
||||||
|
|
||||||
capi-test: capi.o capiconn.o bchan.o hdlr_raw_loop.o hdlr_raw_prbs.o
|
libprbs.a: prbs/prbs.o prbs/rx.o prbs/tx.o
|
||||||
|
$(AR) r $@ $^
|
||||||
|
|
||||||
|
capi-test: capi.o capiconn.o bchan.o hdlr_raw_loop.o hdlr_raw_prbs.o libprbs.a
|
||||||
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
|
2
bchan.h
2
bchan.h
|
@ -32,7 +32,7 @@ struct bchan_handler_ops {
|
||||||
/* initialize whatever handler-private state (call setup) */
|
/* initialize whatever handler-private state (call setup) */
|
||||||
int (*init)(struct call_state *cst);
|
int (*init)(struct call_state *cst);
|
||||||
/* receive data (ISDN -> handler) */
|
/* receive data (ISDN -> handler) */
|
||||||
void (*rx_data)(struct call_state *cst, const uint8_t *data, uint8_t len);
|
void (*rx_data)(struct call_state *cst, const uint8_t *data, size_t len);
|
||||||
/* destroy whatever handler-private state (call teardown) */
|
/* destroy whatever handler-private state (call teardown) */
|
||||||
void (*fini)(struct call_state *cst);
|
void (*fini)(struct call_state *cst);
|
||||||
};
|
};
|
||||||
|
|
2
capi.c
2
capi.c
|
@ -253,7 +253,7 @@ struct capi_inst *capi_init(void *ctx)
|
||||||
if (!ci)
|
if (!ci)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
rc = capi20_register(1, 8, 128, &ci->applid);
|
rc = capi20_register(1, 8, 1280, &ci->applid);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
fprintf(stderr, "Error in capi_register: %s\n", capi_info2str(rc));
|
fprintf(stderr, "Error in capi_register: %s\n", capi_info2str(rc));
|
||||||
talloc_free(ci);
|
talloc_free(ci);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* Raw/Transparent B-Channel loop-back */
|
||||||
|
|
||||||
#include "bchan.h"
|
#include "bchan.h"
|
||||||
|
|
||||||
|
@ -7,7 +8,7 @@ static int raw_loop_init(struct call_state *cst)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void raw_loop_rx(struct call_state *cst, const uint8_t *data, uint8_t len)
|
static void raw_loop_rx(struct call_state *cst, const uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
/* echo whatever we received */
|
/* echo whatever we received */
|
||||||
bchan_call_tx(cst, data, len);
|
bchan_call_tx(cst, data, len);
|
||||||
|
|
|
@ -1,35 +1,44 @@
|
||||||
|
/* Raw/Transparent B-channel with PRBS (pseudo-random bit sequence),
|
||||||
|
* useful for BERT (Bit Error Rate Test) */
|
||||||
|
|
||||||
#include <osmocom/core/utils.h>
|
#include <osmocom/core/utils.h>
|
||||||
#include <osmocom/core/prbs.h>
|
|
||||||
|
|
||||||
#include "bchan.h"
|
#include "bchan.h"
|
||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
|
#include "prbs/prbs.h"
|
||||||
|
|
||||||
|
#define PRBS_ORDER 11
|
||||||
|
#define PRBS_BITLEN (1 << PRBS_ORDER)
|
||||||
|
|
||||||
|
|
||||||
struct raw_prbs_priv {
|
struct raw_prbs_priv {
|
||||||
struct osmo_prbs_state prbs;
|
struct timeslot_state ts;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int raw_prbs_init(struct call_state *cst)
|
static int raw_prbs_init(struct call_state *cst)
|
||||||
{
|
{
|
||||||
struct raw_prbs_priv *rpp;
|
struct raw_prbs_priv *rpp;
|
||||||
|
|
||||||
rpp = cst->priv = talloc_zero(cst, struct raw_prbs_priv);
|
rpp = cst->priv = talloc_zero(cst, struct raw_prbs_priv);
|
||||||
if (!rpp)
|
if (!rpp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
osmo_prbs_state_init(&rpp->prbs, &osmo_prbs15);
|
|
||||||
|
ts_init_prbs_tx(&rpp->ts, 0);
|
||||||
|
ts_init_prbs_rx(&rpp->ts, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void raw_prbs_rx(struct call_state *cst, const uint8_t *data, uint8_t len)
|
static void raw_prbs_rx(struct call_state *cst, const uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
struct raw_prbs_priv *rpp = cst->priv;
|
struct raw_prbs_priv *rpp = cst->priv;
|
||||||
uint8_t tx_ubit[len*8];
|
uint8_t tx_buf[len];
|
||||||
uint8_t tx_pbit[len];
|
|
||||||
/* TODO: process what we received */
|
prbs_process_rx(&rpp->ts.rx, data, len);
|
||||||
|
|
||||||
/* generate respective number of PRBS bits and transmit them */
|
/* generate respective number of PRBS bits and transmit them */
|
||||||
osmo_prbs_get_ubits(tx_ubit, len, &rpp->prbs);
|
prbs_process_tx(&rpp->ts, tx_buf, len);
|
||||||
osmo_ubit2pbit(tx_pbit, tx_ubit, len*8);
|
bchan_call_tx(cst, tx_buf, len);
|
||||||
bchan_call_tx(cst, tx_pbit, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void raw_prbs_fini(struct call_state *cst)
|
static void raw_prbs_fini(struct call_state *cst)
|
||||||
|
|
|
@ -0,0 +1,183 @@
|
||||||
|
/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published
|
||||||
|
* by the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
#include <osmocom/core/prbs.h>
|
||||||
|
|
||||||
|
#include "prbs.h"
|
||||||
|
|
||||||
|
/* according to https://users.ece.cmu.edu/~koopman/lfsr/index.html all below
|
||||||
|
* coefficients should render maximal length LFSRs of 11bit (2048) length */
|
||||||
|
static const uint32_t prbs11_coeff[] = {
|
||||||
|
0x402,
|
||||||
|
0x40B,
|
||||||
|
0x415,
|
||||||
|
0x416,
|
||||||
|
0x423,
|
||||||
|
0x431,
|
||||||
|
0x432,
|
||||||
|
0x438,
|
||||||
|
0x43D,
|
||||||
|
0x446,
|
||||||
|
0x44A,
|
||||||
|
0x44F,
|
||||||
|
0x454,
|
||||||
|
0x458,
|
||||||
|
0x467,
|
||||||
|
0x468,
|
||||||
|
0x470,
|
||||||
|
0x473,
|
||||||
|
0x475,
|
||||||
|
0x47A,
|
||||||
|
0x486,
|
||||||
|
0x489,
|
||||||
|
0x492,
|
||||||
|
0x494,
|
||||||
|
0x49D,
|
||||||
|
0x49E,
|
||||||
|
0x4A2,
|
||||||
|
0x4A4,
|
||||||
|
0x4A8,
|
||||||
|
0x4AD,
|
||||||
|
0x4B9,
|
||||||
|
0x4BA,
|
||||||
|
0x4BF,
|
||||||
|
0x4C1,
|
||||||
|
0x4C7,
|
||||||
|
0x4D5,
|
||||||
|
0x4D6,
|
||||||
|
0x4DC,
|
||||||
|
0x4E3,
|
||||||
|
0x4EC,
|
||||||
|
0x4F2,
|
||||||
|
0x4FB,
|
||||||
|
0x500,
|
||||||
|
0x503,
|
||||||
|
0x509,
|
||||||
|
0x50A,
|
||||||
|
0x514,
|
||||||
|
0x524,
|
||||||
|
0x530,
|
||||||
|
0x536,
|
||||||
|
0x53C,
|
||||||
|
0x53F,
|
||||||
|
0x542,
|
||||||
|
0x548,
|
||||||
|
0x54E,
|
||||||
|
0x553,
|
||||||
|
0x555,
|
||||||
|
0x559,
|
||||||
|
0x55A,
|
||||||
|
0x56A,
|
||||||
|
0x56F,
|
||||||
|
0x574,
|
||||||
|
0x577,
|
||||||
|
0x578,
|
||||||
|
0x57D,
|
||||||
|
0x581,
|
||||||
|
0x584,
|
||||||
|
0x588,
|
||||||
|
0x599,
|
||||||
|
0x59F,
|
||||||
|
0x5A0,
|
||||||
|
0x5A5,
|
||||||
|
0x5AC,
|
||||||
|
0x5AF,
|
||||||
|
0x5B2,
|
||||||
|
0x5B7,
|
||||||
|
0x5BE,
|
||||||
|
0x5C3,
|
||||||
|
0x5C5,
|
||||||
|
0x5C9,
|
||||||
|
0x5CA,
|
||||||
|
0x5D7,
|
||||||
|
0x5DB,
|
||||||
|
0x5DE,
|
||||||
|
0x5E4,
|
||||||
|
0x5ED,
|
||||||
|
0x5EE,
|
||||||
|
0x5F3,
|
||||||
|
0x5F6,
|
||||||
|
0x605,
|
||||||
|
0x606,
|
||||||
|
0x60C,
|
||||||
|
0x60F,
|
||||||
|
0x62B,
|
||||||
|
0x630,
|
||||||
|
0x635,
|
||||||
|
0x639,
|
||||||
|
0x642,
|
||||||
|
0x644,
|
||||||
|
0x64B
|
||||||
|
};
|
||||||
|
|
||||||
|
/* build the PRBS description for a given timeslot number */
|
||||||
|
void prbs_for_ts_nr(struct osmo_prbs *prbs, uint8_t ts_nr)
|
||||||
|
{
|
||||||
|
|
||||||
|
OSMO_ASSERT(ts_nr < ARRAY_SIZE(prbs11_coeff));
|
||||||
|
prbs->name = "custom";
|
||||||
|
prbs->len = 11;
|
||||||
|
prbs->coeff = prbs11_coeff[ts_nr];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compute one full sequence of the given PRBS */
|
||||||
|
void prbs_precomp(struct prbs_precomp *out, const struct osmo_prbs *prbs)
|
||||||
|
{
|
||||||
|
struct osmo_prbs_state prbs_s;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
osmo_prbs_state_init(&prbs_s, prbs);
|
||||||
|
for (i = 0; i < sizeof(out->bytes); i++) {
|
||||||
|
ubit_t ubit[8];
|
||||||
|
osmo_prbs_get_ubits(ubit, sizeof(ubit), &prbs_s);
|
||||||
|
osmo_ubit2pbit(&out->bytes[i], ubit, sizeof(ubit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ts_init_prbs_tx(struct timeslot_state *ts, unsigned int prbs_offs_tx)
|
||||||
|
{
|
||||||
|
unsigned int prbs_nr = prbs_offs_tx + ts->ofd.priv_nr;
|
||||||
|
/* initialize the transmit-side PRNG for this slot */
|
||||||
|
printf("Selecting PRBS11 #%02u for Tx of TS%02u\n", prbs_nr, ts->ofd.priv_nr);
|
||||||
|
prbs_for_ts_nr(&ts->tx.prbs, prbs_nr);
|
||||||
|
prbs_precomp(&ts->tx.prbs_pc, &ts->tx.prbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ts_init_prbs_rx(struct timeslot_state *ts, unsigned int prbs_offs_rx)
|
||||||
|
{
|
||||||
|
unsigned int prbs_nr = prbs_offs_rx + ts->ofd.priv_nr;
|
||||||
|
/* initialize the receive-side PRNG for this slot */
|
||||||
|
ubit_t ubit[PRBS_LEN*2];
|
||||||
|
printf("Selecting PRBS11 #%02u for Rx of TS%02u\n", prbs_nr, ts->ofd.priv_nr);
|
||||||
|
prbs_for_ts_nr(&ts->rx.prbs, prbs_nr);
|
||||||
|
prbs_precomp(&ts->rx.prbs_pc[0], &ts->rx.prbs);
|
||||||
|
osmo_pbit2ubit(ubit, ts->rx.prbs_pc[0].bytes, PRBS_LEN);
|
||||||
|
/* copy buffer twice back-to-back */
|
||||||
|
memcpy(ubit+PRBS_LEN, ubit, PRBS_LEN);
|
||||||
|
|
||||||
|
/* pre-compute bit-shifted versions */
|
||||||
|
for (int i = 1; i < ARRAY_SIZE(ts->rx.prbs_pc); i++) {
|
||||||
|
osmo_ubit2pbit_ext(ts->rx.prbs_pc[i].bytes, 0, ubit, i, PRBS_LEN, 0);
|
||||||
|
//printf("%d: %s\n", i, osmo_hexdump_nospc(ts->prbs_pc[i].bytes, sizeof(ts->prbs_pc[i].bytes)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <osmocom/core/prbs.h>
|
||||||
|
#include <osmocom/core/select.h>
|
||||||
|
|
||||||
|
#define MAX_NR_TS 32
|
||||||
|
#define PRBS_LEN 2048
|
||||||
|
|
||||||
|
/* prbs.c */
|
||||||
|
|
||||||
|
struct timeslot_state;
|
||||||
|
struct prbs_precomp {
|
||||||
|
uint8_t bytes[PRBS_LEN/8];
|
||||||
|
};
|
||||||
|
|
||||||
|
void prbs_for_ts_nr(struct osmo_prbs *prbs, uint8_t ts_nr);
|
||||||
|
|
||||||
|
void prbs_precomp(struct prbs_precomp *out, const struct osmo_prbs *prbs);
|
||||||
|
void ts_init_prbs_tx(struct timeslot_state *ts, unsigned int prbs_offs_tx);
|
||||||
|
void ts_init_prbs_rx(struct timeslot_state *ts, unsigned int prbs_offs_rx);
|
||||||
|
|
||||||
|
/* utils.c */
|
||||||
|
uint8_t bits_set_in_byte(uint8_t byte);
|
||||||
|
void cfg_dahdi_buffer(int fd);
|
||||||
|
void set_realtime(int rt_prio);
|
||||||
|
|
||||||
|
|
||||||
|
struct timeslot_state_tx {
|
||||||
|
struct osmo_prbs prbs; /* PRBS definition */
|
||||||
|
struct prbs_precomp prbs_pc; /* pre-computed PRBS bytes */
|
||||||
|
unsigned int prbs_pc_idx; /* next to-be-transmitted byte offset in prbs_pc */
|
||||||
|
bool active; /* started tx ? */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct timeslot_state_rx {
|
||||||
|
struct osmo_prbs prbs; /* PRBS definition */
|
||||||
|
struct prbs_precomp prbs_pc[8]; /* bit-shifted pre-computed PRBS sequences */
|
||||||
|
struct {
|
||||||
|
bool has_sync; /* do we have a PRBS sync? */
|
||||||
|
struct timespec ts_sync; /* time at which sync was established */
|
||||||
|
unsigned int prbs_pc_num; /* index to prbs_pc[] array */
|
||||||
|
unsigned int prbs_pc_offset; /* offset of next byte into prbs_pc[pc_num].bytes[] */
|
||||||
|
|
||||||
|
unsigned int num_bit_err; /* bit errors since last sync */
|
||||||
|
unsigned int num_sync_loss; /* number of sync losses since start */
|
||||||
|
} sync_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct timeslot_state {
|
||||||
|
struct osmo_fd ofd;
|
||||||
|
struct timeslot_state_tx tx;
|
||||||
|
struct timeslot_state_rx rx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test_state {
|
||||||
|
struct timeslot_state ts[MAX_NR_TS];
|
||||||
|
unsigned int next_unused_ts;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* rx.c */
|
||||||
|
void prbs_process_rx(struct timeslot_state_rx *tsr, const uint8_t *data, unsigned int len);
|
||||||
|
|
||||||
|
/* tx.c */
|
||||||
|
void prbs_process_tx(struct timeslot_state *ts, uint8_t *buf, int len);
|
|
@ -0,0 +1,119 @@
|
||||||
|
/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published
|
||||||
|
* by the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/select.h>
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
|
||||||
|
#include "prbs.h"
|
||||||
|
|
||||||
|
/* we could generate a lookup table at start ... */
|
||||||
|
uint8_t bits_set_in_byte(uint8_t byte)
|
||||||
|
{
|
||||||
|
uint8_t ret = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (byte & (1 << i))
|
||||||
|
ret += 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t next_prbs_pc_byte(struct timeslot_state_rx *tsr)
|
||||||
|
{
|
||||||
|
const struct prbs_precomp *pc = &tsr->prbs_pc[tsr->sync_state.prbs_pc_num];
|
||||||
|
uint8_t ret = pc->bytes[tsr->sync_state.prbs_pc_offset];
|
||||||
|
tsr->sync_state.prbs_pc_offset = (tsr->sync_state.prbs_pc_offset + 1) % sizeof(pc->bytes);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compare if received buffer matches PRBS; count number of different bits */
|
||||||
|
static unsigned int compare_buf(struct timeslot_state_rx *tsr, const uint8_t *data, unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned int i, num_wrong_bits = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
uint8_t bt = next_prbs_pc_byte(tsr);
|
||||||
|
if (data[i] != bt) {
|
||||||
|
uint8_t x = data[i] ^ bt;
|
||||||
|
num_wrong_bits += bits_set_in_byte(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num_wrong_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process incoming received data; try to correlate with prbs sequence */
|
||||||
|
void prbs_process_rx(struct timeslot_state_rx *tsr, const uint8_t *data, unsigned int len)
|
||||||
|
{
|
||||||
|
if (!tsr->sync_state.has_sync) {
|
||||||
|
unsigned int pc_num;
|
||||||
|
/* we haven't synced yet and must attempt to sync to the pattern. We will try
|
||||||
|
* to match each pattern */
|
||||||
|
for (pc_num = 0; pc_num < ARRAY_SIZE(tsr->prbs_pc); pc_num++) {
|
||||||
|
const struct prbs_precomp *pc = &tsr->prbs_pc[pc_num];
|
||||||
|
uint8_t *found;
|
||||||
|
long int offset;
|
||||||
|
|
||||||
|
OSMO_ASSERT(len > sizeof(pc->bytes));
|
||||||
|
found = memmem(data, len, pc->bytes, sizeof(pc->bytes));
|
||||||
|
if (!found)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
offset = (found - data);
|
||||||
|
printf("FOUND SYNC (pc_num=%u, offset=%li)\n", pc_num, offset);
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &tsr->sync_state.ts_sync);
|
||||||
|
tsr->sync_state.has_sync = true;
|
||||||
|
tsr->sync_state.prbs_pc_num = pc_num;
|
||||||
|
tsr->sync_state.prbs_pc_offset = (sizeof(pc->bytes) - offset) % sizeof(pc->bytes);
|
||||||
|
tsr->sync_state.num_bit_err = 0;
|
||||||
|
/* FIXME: compare the remainder of the buffer */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tsr->sync_state.has_sync) {
|
||||||
|
unsigned int num_wrong_bits;
|
||||||
|
/* we already have sync */
|
||||||
|
num_wrong_bits = compare_buf(tsr, data, len);
|
||||||
|
if (num_wrong_bits >= len*8/4) { /* more than 25% of wrong bits */
|
||||||
|
struct timespec ts_now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &ts_now);
|
||||||
|
printf("LOST SYNC after %u of %u wrong bits in one buffer; "
|
||||||
|
"until now, total bit errors %u in %lu seconds\n",
|
||||||
|
num_wrong_bits, len*8, tsr->sync_state.num_bit_err,
|
||||||
|
ts_now.tv_sec - tsr->sync_state.ts_sync.tv_sec);
|
||||||
|
tsr->sync_state.has_sync = false;
|
||||||
|
tsr->sync_state.num_sync_loss++;
|
||||||
|
}
|
||||||
|
tsr->sync_state.num_bit_err += num_wrong_bits;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published
|
||||||
|
* by the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/select.h>
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
|
||||||
|
#include "prbs.h"
|
||||||
|
|
||||||
|
void prbs_process_tx(struct timeslot_state *ts, uint8_t *buf, int len)
|
||||||
|
{
|
||||||
|
int i, rc;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
buf[i] = ts->tx.prbs_pc.bytes[ts->tx.prbs_pc_idx];
|
||||||
|
ts->tx.prbs_pc_idx = (ts->tx.prbs_pc_idx + 1) % sizeof(ts->tx.prbs_pc);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue