comparison spandsp-0.0.6pre17/src/bert.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * bert.c - Bit error rate tests.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2004 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: bert.c,v 1.33 2009/04/14 16:04:53 steveu Exp $
26 */
27
28 #if defined(HAVE_CONFIG_H)
29 #include "config.h"
30 #endif
31
32 #include <inttypes.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <assert.h>
37 #include <time.h>
38
39 #include "spandsp/telephony.h"
40 #include "spandsp/logging.h"
41 #include "spandsp/async.h"
42 #include "spandsp/bert.h"
43
44 #include "spandsp/private/logging.h"
45 #include "spandsp/private/bert.h"
46
47 #define MEASUREMENT_STEP 100
48
49 static const char *qbf = "VoyeZ Le BricK GeanT QuE J'ExaminE PreS Du WharF 123 456 7890 + - * : = $ % ( )"
50 "ThE QuicK BrowN FoX JumpS OveR ThE LazY DoG 123 456 7890 + - * : = $ % ( )";
51
52 SPAN_DECLARE(const char *) bert_event_to_str(int event)
53 {
54 switch (event)
55 {
56 case BERT_REPORT_SYNCED:
57 return "synced";
58 case BERT_REPORT_UNSYNCED:
59 return "unsync'ed";
60 case BERT_REPORT_REGULAR:
61 return "regular";
62 case BERT_REPORT_GT_10_2:
63 return "error rate > 1 in 10^2";
64 case BERT_REPORT_LT_10_2:
65 return "error rate < 1 in 10^2";
66 case BERT_REPORT_LT_10_3:
67 return "error rate < 1 in 10^3";
68 case BERT_REPORT_LT_10_4:
69 return "error rate < 1 in 10^4";
70 case BERT_REPORT_LT_10_5:
71 return "error rate < 1 in 10^5";
72 case BERT_REPORT_LT_10_6:
73 return "error rate < 1 in 10^6";
74 case BERT_REPORT_LT_10_7:
75 return "error rate < 1 in 10^7";
76 }
77 return "???";
78 }
79 /*- End of function --------------------------------------------------------*/
80
81 SPAN_DECLARE(int) bert_get_bit(bert_state_t *s)
82 {
83 int bit;
84
85 if (s->limit && s->tx.bits >= s->limit)
86 return SIG_STATUS_END_OF_DATA;
87 bit = 0;
88 switch (s->pattern_class)
89 {
90 case 0:
91 bit = s->tx.reg & 1;
92 s->tx.reg = (s->tx.reg >> 1) | ((s->tx.reg & 1) << s->shift2);
93 break;
94 case 1:
95 bit = s->tx.reg & 1;
96 s->tx.reg = (s->tx.reg >> 1) | (((s->tx.reg ^ (s->tx.reg >> s->shift)) & 1) << s->shift2);
97 if (s->max_zeros)
98 {
99 /* This generator suppresses runs >s->max_zeros */
100 if (bit)
101 {
102 if (++s->tx.zeros > s->max_zeros)
103 {
104 s->tx.zeros = 0;
105 bit ^= 1;
106 }
107 }
108 else
109 {
110 s->tx.zeros = 0;
111 }
112 }
113 bit ^= s->invert;
114 break;
115 case 2:
116 if (s->tx.step_bit == 0)
117 {
118 s->tx.step_bit = 7;
119 s->tx.reg = qbf[s->tx.step++];
120 if (s->tx.reg == 0)
121 {
122 s->tx.reg = 'V';
123 s->tx.step = 1;
124 }
125 }
126 bit = s->tx.reg & 1;
127 s->tx.reg >>= 1;
128 s->tx.step_bit--;
129 break;
130 }
131 s->tx.bits++;
132 return bit;
133 }
134 /*- End of function --------------------------------------------------------*/
135
136 static void assess_error_rate(bert_state_t *s)
137 {
138 int i;
139 int j;
140 int sum;
141 int test;
142
143 /* We assess the error rate in decadic steps. For each decade we assess the error over 10 times
144 the number of bits, to smooth the result. This means we assess the 1 in 100 rate based on 1000 bits
145 (i.e. we look for >=10 errors in 1000 bits). We make an assessment every 100 bits, using a sliding
146 window over the last 1000 bits. We assess the 1 in 1000 rate over 10000 bits in a similar way, and
147 so on for the lower error rates. */
148 test = TRUE;
149 for (i = 2; i <= 7; i++)
150 {
151 if (++s->decade_ptr[i] < 10)
152 break;
153 /* This decade has reached 10 snapshots, so we need to touch the next decade */
154 s->decade_ptr[i] = 0;
155 /* Sum the last 10 snapshots from this decade, to see if we overflow into the next decade */
156 for (sum = 0, j = 0; j < 10; j++)
157 sum += s->decade_bad[i][j];
158 if (test && sum > 10)
159 {
160 /* We overflow into the next decade */
161 test = FALSE;
162 if (s->error_rate != i && s->reporter)
163 s->reporter(s->user_data, BERT_REPORT_GT_10_2 + i - 2, &s->results);
164 s->error_rate = i;
165 }
166 s->decade_bad[i][0] = 0;
167 if (i < 7)
168 s->decade_bad[i + 1][s->decade_ptr[i + 1]] = sum;
169 }
170 if (i > 7)
171 {
172 if (s->decade_ptr[i] >= 10)
173 s->decade_ptr[i] = 0;
174 if (test)
175 {
176 if (s->error_rate != i && s->reporter)
177 s->reporter(s->user_data, BERT_REPORT_GT_10_2 + i - 2, &s->results);
178 s->error_rate = i;
179 }
180 }
181 else
182 {
183 s->decade_bad[i][s->decade_ptr[i]] = 0;
184 }
185 }
186 /*- End of function --------------------------------------------------------*/
187
188 SPAN_DECLARE(void) bert_put_bit(bert_state_t *s, int bit)
189 {
190 if (bit < 0)
191 {
192 /* Special conditions */
193 printf("Status is %s (%d)\n", signal_status_to_str(bit), bit);
194 return;
195 }
196 bit = (bit & 1) ^ s->invert;
197 s->rx.bits++;
198 switch (s->pattern_class)
199 {
200 case 0:
201 if (s->rx.resync)
202 {
203 s->rx.reg = (s->rx.reg >> 1) | (bit << s->shift2);
204 s->rx.ref_reg = (s->rx.ref_reg >> 1) | ((s->rx.ref_reg & 1) << s->shift2);
205 if (s->rx.reg == s->rx.ref_reg)
206 {
207 if (++s->rx.resync > s->resync_time)
208 {
209 s->rx.resync = 0;
210 if (s->reporter)
211 s->reporter(s->user_data, BERT_REPORT_SYNCED, &s->results);
212 }
213 }
214 else
215 {
216 s->rx.resync = 2;
217 s->rx.ref_reg = s->rx.master_reg;
218 }
219 }
220 else
221 {
222 s->results.total_bits++;
223 if ((bit ^ s->rx.ref_reg) & 1)
224 s->results.bad_bits++;
225 s->rx.ref_reg = (s->rx.ref_reg >> 1) | ((s->rx.ref_reg & 1) << s->shift2);
226 }
227 break;
228 case 1:
229 if (s->rx.resync)
230 {
231 /* If we get a reasonable period for which we correctly predict the
232 next bit, we must be in sync. */
233 /* Don't worry about max. zeros tests when resyncing.
234 It might just extend the resync time a little. Trying
235 to include the test might affect robustness. */
236 if (bit == (int) ((s->rx.reg >> s->shift) & 1))
237 {
238 if (++s->rx.resync > s->resync_time)
239 {
240 s->rx.resync = 0;
241 if (s->reporter)
242 s->reporter(s->user_data, BERT_REPORT_SYNCED, &s->results);
243 }
244 }
245 else
246 {
247 s->rx.resync = 2;
248 s->rx.reg ^= s->mask;
249 }
250 }
251 else
252 {
253 s->results.total_bits++;
254 if (s->max_zeros)
255 {
256 /* This generator suppresses runs >s->max_zeros */
257 if ((s->rx.reg & s->mask))
258 {
259 if (++s->rx.zeros > s->max_zeros)
260 {
261 s->rx.zeros = 0;
262 bit ^= 1;
263 }
264 }
265 else
266 {
267 s->rx.zeros = 0;
268 }
269 }
270 if (bit != (int) ((s->rx.reg >> s->shift) & 1))
271 {
272 s->results.bad_bits++;
273 s->rx.resync_bad_bits++;
274 s->decade_bad[2][s->decade_ptr[2]]++;
275 }
276 if (--s->rx.measurement_step <= 0)
277 {
278 /* Every hundred bits we need to do the error rate measurement */
279 s->rx.measurement_step = MEASUREMENT_STEP;
280 assess_error_rate(s);
281 }
282 if (--s->rx.resync_cnt <= 0)
283 {
284 /* Check if there were enough bad bits during this period to
285 justify a resync. */
286 if (s->rx.resync_bad_bits >= (s->rx.resync_len*s->rx.resync_percent)/100)
287 {
288 s->rx.resync = 1;
289 s->results.resyncs++;
290 if (s->reporter)
291 s->reporter(s->user_data, BERT_REPORT_UNSYNCED, &s->results);
292 }
293 s->rx.resync_cnt = s->rx.resync_len;
294 s->rx.resync_bad_bits = 0;
295 }
296 }
297 s->rx.reg = (s->rx.reg >> 1) | (((s->rx.reg ^ (s->rx.reg >> s->shift)) & 1) << s->shift2);
298 break;
299 case 2:
300 s->rx.reg = (s->rx.reg >> 1) | (bit << 6);
301 /* TODO: There is no mechanism for synching yet. This only works if things start in sync. */
302 if (++s->rx.step_bit == 7)
303 {
304 s->rx.step_bit = 0;
305 if ((int) s->rx.reg != qbf[s->rx.step])
306 {
307 /* We need to work out the number of actual bad bits here. We need to look at the
308 error rate, and see it a resync is needed. etc. */
309 s->results.bad_bits++;
310 }
311 if (qbf[++s->rx.step] == '\0')
312 s->rx.step = 0;
313 }
314 s->results.total_bits++;
315 break;
316 }
317 if (s->report_frequency > 0)
318 {
319 if (--s->rx.report_countdown <= 0)
320 {
321 if (s->reporter)
322 s->reporter(s->user_data, BERT_REPORT_REGULAR, &s->results);
323 s->rx.report_countdown = s->report_frequency;
324 }
325 }
326 }
327 /*- End of function --------------------------------------------------------*/
328
329 SPAN_DECLARE(int) bert_result(bert_state_t *s, bert_results_t *results)
330 {
331 results->total_bits = s->results.total_bits;
332 results->bad_bits = s->results.bad_bits;
333 results->resyncs = s->results.resyncs;
334 return sizeof(*results);
335 }
336 /*- End of function --------------------------------------------------------*/
337
338 SPAN_DECLARE(void) bert_set_report(bert_state_t *s, int freq, bert_report_func_t reporter, void *user_data)
339 {
340 s->report_frequency = freq;
341 s->reporter = reporter;
342 s->user_data = user_data;
343
344 s->rx.report_countdown = s->report_frequency;
345 }
346 /*- End of function --------------------------------------------------------*/
347
348 SPAN_DECLARE(bert_state_t *) bert_init(bert_state_t *s, int limit, int pattern, int resync_len, int resync_percent)
349 {
350 int i;
351 int j;
352
353 if (s == NULL)
354 {
355 if ((s = (bert_state_t *) malloc(sizeof(*s))) == NULL)
356 return NULL;
357 }
358 memset(s, 0, sizeof(*s));
359
360 s->pattern = pattern;
361 s->limit = limit;
362 s->reporter = NULL;
363 s->user_data = NULL;
364 s->report_frequency = 0;
365
366 s->resync_time = 72;
367 s->invert = 0;
368 switch (s->pattern)
369 {
370 case BERT_PATTERN_ZEROS:
371 s->tx.reg = 0;
372 s->shift2 = 31;
373 s->pattern_class = 0;
374 break;
375 case BERT_PATTERN_ONES:
376 s->tx.reg = ~((uint32_t) 0);
377 s->shift2 = 31;
378 s->pattern_class = 0;
379 break;
380 case BERT_PATTERN_7_TO_1:
381 s->tx.reg = 0xFEFEFEFE;
382 s->shift2 = 31;
383 s->pattern_class = 0;
384 break;
385 case BERT_PATTERN_3_TO_1:
386 s->tx.reg = 0xEEEEEEEE;
387 s->shift2 = 31;
388 s->pattern_class = 0;
389 break;
390 case BERT_PATTERN_1_TO_1:
391 s->tx.reg = 0xAAAAAAAA;
392 s->shift2 = 31;
393 s->pattern_class = 0;
394 break;
395 case BERT_PATTERN_1_TO_3:
396 s->tx.reg = 0x11111111;
397 s->shift2 = 31;
398 s->pattern_class = 0;
399 break;
400 case BERT_PATTERN_1_TO_7:
401 s->tx.reg = 0x01010101;
402 s->shift2 = 31;
403 s->pattern_class = 0;
404 break;
405 case BERT_PATTERN_QBF:
406 s->tx.reg = 0;
407 s->pattern_class = 2;
408 break;
409 case BERT_PATTERN_ITU_O151_23:
410 s->pattern_class = 1;
411 s->tx.reg = 0x7FFFFF;
412 s->mask = 0x20;
413 s->shift = 5;
414 s->shift2 = 22;
415 s->invert = 1;
416 s->resync_time = 56;
417 s->max_zeros = 0;
418 break;
419 case BERT_PATTERN_ITU_O151_20:
420 s->pattern_class = 1;
421 s->tx.reg = 0xFFFFF;
422 s->mask = 0x8;
423 s->shift = 3;
424 s->shift2 = 19;
425 s->invert = 1;
426 s->resync_time = 50;
427 s->max_zeros = 14;
428 break;
429 case BERT_PATTERN_ITU_O151_15:
430 s->pattern_class = 1;
431 s->tx.reg = 0x7FFF;
432 s->mask = 0x2;
433 s->shift = 1;
434 s->shift2 = 14;
435 s->invert = 1;
436 s->resync_time = 40;
437 s->max_zeros = 0;
438 break;
439 case BERT_PATTERN_ITU_O152_11:
440 s->pattern_class = 1;
441 s->tx.reg = 0x7FF;
442 s->mask = 0x4;
443 s->shift = 2;
444 s->shift2 = 10;
445 s->invert = 0;
446 s->resync_time = 32;
447 s->max_zeros = 0;
448 break;
449 case BERT_PATTERN_ITU_O153_9:
450 s->pattern_class = 1;
451 s->tx.reg = 0x1FF;
452 s->mask = 0x10;
453 s->shift = 4;
454 s->shift2 = 8;
455 s->invert = 0;
456 s->resync_time = 28;
457 s->max_zeros = 0;
458 break;
459 }
460 s->tx.bits = 0;
461 s->tx.step = 0;
462 s->tx.step_bit = 0;
463 s->tx.zeros = 0;
464
465 s->rx.reg = s->tx.reg;
466 s->rx.ref_reg = s->rx.reg;
467 s->rx.master_reg = s->rx.ref_reg;
468 s->rx.bits = 0;
469 s->rx.step = 0;
470 s->rx.step_bit = 0;
471
472 s->rx.resync = 1;
473 s->rx.resync_cnt = resync_len;
474 s->rx.resync_bad_bits = 0;
475 s->rx.resync_len = resync_len;
476 s->rx.resync_percent = resync_percent;
477
478 s->results.total_bits = 0;
479 s->results.bad_bits = 0;
480 s->results.resyncs = 0;
481
482 s->rx.report_countdown = 0;
483
484 for (i = 0; i < 8; i++)
485 {
486 for (j = 0; j < 10; j++)
487 s->decade_bad[i][j] = 0;
488 s->decade_ptr[i] = 0;
489 }
490 s->error_rate = 8;
491 s->rx.measurement_step = MEASUREMENT_STEP;
492
493 span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
494 span_log_set_protocol(&s->logging, "BERT");
495
496 return s;
497 }
498 /*- End of function --------------------------------------------------------*/
499
500 SPAN_DECLARE(int) bert_release(bert_state_t *s)
501 {
502 return 0;
503 }
504 /*- End of function --------------------------------------------------------*/
505
506 SPAN_DECLARE(int) bert_free(bert_state_t *s)
507 {
508 free(s);
509 return 0;
510 }
511 /*- End of function --------------------------------------------------------*/
512 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.