diff options
| author | Matthias (think) <matthias@mpb.li> | 2012-07-11 11:49:12 +0200 | 
|---|---|---|
| committer | Matthias (think) <matthias@mpb.li> | 2012-07-11 11:49:12 +0200 | 
| commit | bbab73a63b8c7b50e8a8cb228999d45024fad984 (patch) | |
| tree | 81a822aa9bd33cae8a5fb8ade4faa83b652316d9 /src/prbs.c | |
| download | dabmux-bbab73a63b8c7b50e8a8cb228999d45024fad984.tar.gz dabmux-bbab73a63b8c7b50e8a8cb228999d45024fad984.tar.bz2 dabmux-bbab73a63b8c7b50e8a8cb228999d45024fad984.zip | |
added unmodified mmbtools
Diffstat (limited to 'src/prbs.c')
| -rw-r--r-- | src/prbs.c | 140 | 
1 files changed, 140 insertions, 0 deletions
| diff --git a/src/prbs.c b/src/prbs.c new file mode 100644 index 0000000..8a11266 --- /dev/null +++ b/src/prbs.c @@ -0,0 +1,140 @@ +/* +   Copyright (C) 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in Right +   of Canada (Communications Research Center Canada) +   */ +/* +   This file is part of CRC-DabMux. + +   CRC-DabMux 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 3 of the +   License, or (at your option) any later version. + +   CRC-DabMux 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 CRC-DabMux.  If not, see <http://www.gnu.org/licenses/>. +   */ + +#include "prbs.h" + +#include <string.h> +#include <stdlib.h> +#include <limits.h> + + +/* + * Generate a parity check for a 32-bit word. + */ +unsigned long parity_check(unsigned long prbs_accum) +{ +    unsigned long mask=1UL, parity=0UL; +    int i; +    for (i = 0;  i < 32;  ++i) { +        parity ^= ((prbs_accum & mask) != 0UL); +        mask <<= 1; +    } +    return parity; +} + +/* + * Generate a table of matrix products to update a 32-bit PRBS generator. + */ +void gen_prbs_table(void* args) +{ +    prbs_data* data = (prbs_data*)args; +    int i; +    for (i = 0;  i < 4;  ++i) { +        int j; +        for (j = 0;  j < 256;  ++j) { +            unsigned long prbs_accum = ((unsigned long)j << (i * 8)); +            int k; +            for (k = 0;  k < 8;  ++k) { +                prbs_accum = (prbs_accum << 1) +                                ^ parity_check(prbs_accum & data->polynomial); +            } +            data->prbs_table[i][j] = (prbs_accum & 0xff); +        } +    } +} + +/* + * Update a 32-bit PRBS generator eight bits at a time. + */ +unsigned long update_prbs(void* args) +{ +    prbs_data* data = (prbs_data*)args; +    unsigned char acc_lsb = 0; +    int i; +    for (i = 0;  i < 4;  ++i ) { +        acc_lsb ^= data->prbs_table [i] [ (data->accum >> (i * 8) ) & 0xff ]; +    } +    return (data->accum << 8) ^ ((unsigned long)acc_lsb); +} + +/* + * Generate the weight table. + */ +void gen_weight_table(void* args) +{ +    prbs_data* data = (prbs_data*)args;  +    int i; +    for (i = 0;  i < 256;  ++i) { +        unsigned char mask=1U, ones_count = 0U; +        int j; +        for (j = 0;  j < 8;  ++j) { +            ones_count += ((i & mask) != 0U); +            mask = mask << 1; +        } +        data->weight[i] = ones_count; +    } +} + +/* + * Count the number of errors in a block of received data. + */ +unsigned long error_count(void* args, unsigned char *rx_data, +        int rx_data_length) +{ +    prbs_data* data = (prbs_data*)args; +    unsigned long error_count = 0U; +    unsigned long prbs_accum = 0U; +    int i; + +    /* seed the PRBS accumulator */ +    for (i = 0;  i < 4;  ++i) { +        prbs_accum = (prbs_accum << 8) ^ (rx_data[i] ^ data->polarity_mask); +    } + +    /* check the received data */ +    for (i = 0;  i < rx_data_length;  ++i) { +        unsigned char error_pattern = (unsigned char) +                          ((prbs_accum >> 24) +                          ^ (rx_data[i] ^ data->polarity_mask)); +        if (error_pattern != 0U) { +            error_count += data->weight[error_pattern]; +        } +        prbs_accum = update_prbs(data); +    } +    return error_count; +} + +void gen_sequence(void* args, unsigned char *tx_data, int tx_data_length, +        unsigned long polynomial) +{ +    prbs_data* data = (prbs_data*)args; +    unsigned long prbs_accum = 0U; + +    while (prbs_accum < polynomial) { +        prbs_accum <<= 1; +        prbs_accum |= 1; +    } + +    while (tx_data_length-- > 0) { +        prbs_accum = update_prbs(data); +        *(tx_data++) = (unsigned char)(prbs_accum & 0xff); +    } +} | 
