source: trunk/kitgen/csr_test.c@ 175

Last change on this file since 175 was 175, checked in by demin, 12 years ago

initial commit

File size: 18.1 KB
Line 
1#include <string.h>
2#include <stdlib.h>
3#include <memory.h>
4#include <stdio.h>
5#include <math.h>
6#include <tcl.h>
7
8/* ----------------------------------------------------------------- */
9/* Peak detection using undecimated wavelet transform (UWT) */
10/* ----------------------------------------------------------------- */
11
12/* Memory requirements */
13/* tapped delay line: 24 registers */
14/* noise buffer: 16 registers */
15
16#define UWT_ZERO 1000
17#define UWT_LEVEL 3
18
19#define UWT_NOISE_BUFFER_SIZE 16
20#define UWT_NOISE_BUFFER_SIZE_LOG2 4
21
22#define UWT_TYPICAL_START_TIME 16
23#define UWT_TYPICAL_NOISE_TIME 16
24#define UWT_MAX_RISE_TIME 40
25#define UWT_MIN_PEAK_DIST 60
26
27#define UWT_SIGNAL_THRESHOLD 10
28
29static void uwt_bior31_step(int input, int *tap,
30 int *d_reg, int *a_reg, int *peak_reg, int *tmp1_reg, int *tmp2_reg, int *flag1_reg, int *flag2_reg, int *less_reg, int *more_reg,
31 int *d, int *a, int *peak, int *is_min, int *is_max, int level)
32{
33 int i;
34 int index1 = 1 << (level - 1);
35 int index2 = 2 << (level - 1);
36 int index3 = 3 << (level - 1);
37 int peak_index = ((3 << (level - 1)) + 1) >> 1;
38 int peak_shift = ((level - 1) << 1) + (level - 1);
39
40 int d_next, a_next, peak_next;
41 int tmp1_next, tmp2_next, less_next, more_next;
42
43
44 // Tapped delay line: shift one
45 for(i = index3; i > 0; --i)
46 {
47 tap[i] = tap[i-1];
48 }
49
50 // Input in register 0
51 tap[0] = input;
52
53 *d = *d_reg;
54 *a = *a_reg;
55 *peak = *peak_reg;
56 *is_min = *flag2_reg;
57 *is_max = *flag1_reg;
58
59 tmp1_next = tap[index3] + (tap[index2] << 1) + tap[index2];
60 tmp2_next = (tap[index1] << 1) + tap[index1] + tap[0];
61
62 d_next = UWT_ZERO - *tmp1_reg + *tmp2_reg;
63 a_next = *tmp1_reg + *tmp2_reg;
64
65 more_next = (*d_reg > UWT_ZERO);
66 less_next = (*d_reg < UWT_ZERO);
67
68 peak_next = (tap[peak_index + 1] >> peak_shift);
69
70 *flag2_reg = (*more_reg) && (!more_next);
71 *flag1_reg = (*less_reg) && (!less_next);
72
73 *d_reg = d_next;
74 *a_reg = a_next;
75 *peak_reg = peak_next;
76
77 *tmp1_reg = tmp1_next;
78 *tmp2_reg = tmp2_next;
79 *less_reg = less_next;
80 *more_reg = more_next;
81
82
83/*
84 *d = UWT_ZERO - (tap[index3])
85 - (tap[index2] << 1) - tap[index2]
86 + (tap[index1] << 1) + tap[index1]
87 + (tap[0]);
88
89 *a = (tap[index3])
90 + (tap[index2] << 1) + tap[index2]
91 + (tap[index1] << 1) + tap[index1]
92 + (tap[0]);
93
94 *peak = (tap[peak_index] >> peak_shift);
95
96 *is_min = (*d_reg < UWT_ZERO) && (*d >= UWT_ZERO) ? 1 : 0;
97 *is_max = (*d_reg > UWT_ZERO) && (*d <= UWT_ZERO) ? 1 : 0;
98*/
99/*
100 if(((*is_min) || (*is_max)) && (level == 3)) printf("peak -> %d -> %d -> %d\n", (*peak), (*d_reg), (*d));
101*/
102/*
103 *d_reg = *d;
104*/
105}
106
107/* ----------------------------------------------------------------- */
108
109static void uwt_process(int *input, int *noise, int *peak, int *is_min, int *is_max, int *is_valid, int n)
110{
111 int i, j, k;
112 int sample;
113
114 int mode = 0;
115
116 int time_from_start = 0;
117 int time_from_min = 0;
118 int time_from_max = 0;
119
120 int noise_average = 0;
121
122 int noise_buffer[UWT_NOISE_BUFFER_SIZE];
123
124 int pulse_height = 0;
125
126 int size;
127 int d_reg[UWT_LEVEL];
128 int a_reg[UWT_LEVEL], peak_reg[UWT_LEVEL];
129 int tmp1_reg[UWT_LEVEL], tmp2_reg[UWT_LEVEL];
130 int flag1_reg[UWT_LEVEL], flag2_reg[UWT_LEVEL];
131 int less_reg[UWT_LEVEL], more_reg[UWT_LEVEL];
132 int a, d;
133 int *tap[UWT_LEVEL];
134
135 for(j = 0; j < UWT_NOISE_BUFFER_SIZE; ++j)
136 {
137 noise_buffer[j] = 0;
138 }
139
140 // Tapped delay line
141 for(j = 0; j < UWT_LEVEL; ++j)
142 {
143 size = ((3 << j) + 1)*sizeof(int);
144 printf("%d -> %d\n", j+1, ((3 << j) + 1));
145 fflush(stdout);
146 tap[j] = (int *) malloc(size);
147 memset(tap[j], 0, size);
148 d_reg[j] = UWT_ZERO;
149 a_reg[j] = UWT_ZERO;
150 peak_reg[j] = UWT_ZERO;
151 tmp1_reg[j] = UWT_ZERO;
152 tmp2_reg[j] = UWT_ZERO;
153 flag1_reg[j] = UWT_ZERO;
154 flag2_reg[j] = UWT_ZERO;
155 less_reg[j] = UWT_ZERO;
156 more_reg[j] = UWT_ZERO;
157 }
158
159 for(i = 0; i < n; ++i)
160 {
161 sample = input[i];
162 is_valid[i] = 0;
163
164 for(j = 0; j < UWT_LEVEL; ++j)
165 {
166 uwt_bior31_step(sample, tap[j],
167 d_reg+j, a_reg+j, peak_reg+j, tmp1_reg+j, tmp2_reg+j, flag1_reg+j, flag2_reg+j, less_reg+j, more_reg+j,
168 &d, &a, peak+i, is_min+i, is_max+i, j+1);
169 sample = a;
170 }
171
172 if(is_min[i] && mode > 0)
173 {
174 for(j = 0; j < UWT_NOISE_BUFFER_SIZE - 1; ++j)
175 {
176 noise_buffer[j] = noise_buffer[j+1] + peak[i];
177 }
178 noise_buffer[UWT_NOISE_BUFFER_SIZE-1] = peak[i];
179
180 noise_average = noise_buffer[0] >> UWT_NOISE_BUFFER_SIZE_LOG2;
181
182 time_from_min = 0;
183 }
184
185 noise[i] = noise_average;
186
187 switch(mode)
188 {
189 case 0:
190 ++time_from_start;
191
192 if(time_from_start >= UWT_TYPICAL_START_TIME)
193 {
194 mode = 1;
195 time_from_start = 0;
196 }
197 break;
198
199 case 1:
200 if(is_min[i]) ++time_from_start;
201
202 if(time_from_start >= UWT_TYPICAL_NOISE_TIME)
203 {
204 mode = 2;
205 time_from_start = 0;
206 }
207 break;
208
209 case 2:
210 if(is_max[i])
211 {
212 pulse_height = peak[i] - noise_average;
213
214 if(pulse_height > UWT_SIGNAL_THRESHOLD)
215 {
216 printf("%d -> %d -> %d\n", pulse_height, time_from_min, time_from_max);
217 if(time_from_min < UWT_MAX_RISE_TIME &&
218 time_from_max > UWT_MIN_PEAK_DIST
219 )
220 {
221 is_valid[i] = 1;
222 }
223 time_from_max = 0;
224 }
225 }
226
227 ++time_from_min;
228 ++time_from_max;
229
230 break;
231
232 default:
233 /* Do nothing */
234 break;
235 }
236 }
237
238 for(j = 0; j < UWT_LEVEL; ++j)
239 {
240 free(tap[j]);
241 }
242
243}
244
245/* ----------------------------------------------------------------- */
246/* Peak detection using "snake" algorithm */
247/* ----------------------------------------------------------------- */
248
249/* Memory requirements */
250/* noise buffer: 32 registers */
251/* peak buffer: 7 registers */
252
253static void sum8(int *input, int *output, int n)
254{
255 int i, j;
256
257 // Tapped delay line
258 int *tap = (int *) malloc(8*sizeof(int));
259 memset(tap, 0, 8*sizeof(int));
260
261 for(i = 0; i < n; ++i)
262 {
263 // Tapped delay line: shift one
264 for(j = 7; j > 0; --j)
265 {
266 tap[j] = tap[j-1];
267 }
268
269 // Input in register 0
270 tap[0] = input[i];
271
272 output[i] = 0;
273
274 for(j = 0; j < 8; ++j)
275 {
276 output[i] += tap[j];
277 }
278
279 output[i] = output[i] >> 3;
280
281 }
282
283 free(tap);
284}
285
286/* ----------------------------------------------------------------- */
287
288#define PEAK_BUFFER_SIZE 7
289#define NOISE_BUFFER_SIZE 32
290#define NOISE_BUFFER_SIZE_LOG2 5
291
292#define TYPICAL_START_TIME 64
293#define TYPICAL_RISE_TIME 12
294#define TYPICAL_PILEUP_TIME 20
295
296#define SIGNAL_THRESHOLD 10
297
298static void csr_process(int *input, int *noise, int *peak, int *is_max, int n)
299{
300 int i, j, k;
301 int sample;
302
303
304 int mode = 0;
305 int min_sample = 4095;
306
307 int time_from_start = 0;
308 int time_from_min = 0;
309 int time_from_peak = 0;
310
311 int noise_average = 0;
312 int min_noise_average = 4095;
313
314 int noise_buffer[NOISE_BUFFER_SIZE];
315 int peak_buffer[PEAK_BUFFER_SIZE];
316
317 int peak_value = 0;
318 int pulse_height = 0;
319
320 int is_raising, is_stable, is_stored, is_valid, is_pileup;
321
322 for(j = 0; j < NOISE_BUFFER_SIZE; ++j)
323 {
324 noise_buffer[j] = 4095;
325 }
326
327 for(i = 0; i < n; ++i)
328 {
329 sample = input[i];
330 noise[i] = 0;
331 peak[i] = 0;
332 is_max[i] = 0;
333
334 if(mode == 0 || mode == 1)
335 {
336 for(j = 0; j < NOISE_BUFFER_SIZE - 1; ++j)
337 {
338 noise_buffer[j] = noise_buffer[j+1];
339 }
340 noise_buffer[NOISE_BUFFER_SIZE-1] = sample;
341
342 noise_average = 0;
343 for(j = 0; j < NOISE_BUFFER_SIZE; ++j)
344 {
345 noise_average += noise_buffer[j];
346 }
347 noise_average = noise_average >> NOISE_BUFFER_SIZE_LOG2;
348 }
349
350 noise[i] = noise_average;
351
352 for(j = 0; j < PEAK_BUFFER_SIZE - 1; ++j)
353 {
354 peak_buffer[j] = peak_buffer[j+1];
355 }
356 peak_buffer[PEAK_BUFFER_SIZE-1] = sample;
357
358 switch(mode)
359 {
360 case 0:
361 if(noise_average < min_noise_average)
362 {
363 min_noise_average = noise_average;
364 }
365
366 ++time_from_start;
367
368 if(time_from_start >= TYPICAL_START_TIME)
369 {
370 mode = 1;
371 noise_average = min_noise_average;
372 for(j = 0; j < NOISE_BUFFER_SIZE; ++j)
373 {
374 noise_buffer[j] = min_noise_average;
375 }
376 }
377 break;
378
379 case 1:
380 is_raising = 0;
381 is_stable = 0;
382 if(sample >= min_sample)
383 {
384 is_stable = 1;
385 }
386 else
387 {
388 min_sample = sample;
389 }
390 if(peak_buffer[0] < peak_buffer[3]) is_raising = 1;
391 if(is_stable && is_raising)
392 {
393 ++time_from_min;
394 }
395 else
396 {
397 time_from_min = 0;
398 if(!is_raising) min_sample = peak_buffer[3];
399 }
400 if(time_from_min >= TYPICAL_RISE_TIME)
401 {
402 mode = 2;
403 is_stored = 0;
404 is_valid = 0;
405 }
406 break;
407
408 case 2:
409 if(!is_stored)
410 {
411 if(peak_buffer[3] > peak_buffer[0] &&
412 peak_buffer[3] > peak_buffer[6] &&
413 peak_buffer[3] >= peak_buffer[2] &&
414 peak_buffer[3] >= peak_buffer[4])
415 {
416 peak_value = peak_buffer[3];
417 time_from_peak = 3;
418 pulse_height = peak_value - noise_average;
419 if(pulse_height > SIGNAL_THRESHOLD)
420 {
421 is_valid = 1;
422 peak[i] = peak_value;
423 is_max[i] = 1;
424 is_stored = 1;
425 }
426 mode = 3;
427 }
428 }
429 ++time_from_min;
430 is_pileup = 0;
431 break;
432
433 case 3:
434 ++time_from_min;
435 ++time_from_peak;
436 if(time_from_min > TYPICAL_PILEUP_TIME ||
437 time_from_peak > TYPICAL_PILEUP_TIME)
438 {
439 is_pileup = 1;
440 }
441 if(peak_buffer[3] < peak_buffer[0] &&
442 peak_buffer[3] < peak_buffer[6] &&
443 peak_buffer[3] <= peak_buffer[2] &&
444 peak_buffer[3] <= peak_buffer[4])
445 {
446 min_sample = peak_buffer[3];
447 mode = 1;
448 }
449 break;
450
451 default:
452 /* Do nothing */
453 break;
454 }
455 }
456}
457
458/* ----------------------------------------------------------------- */
459/* Interface with Tcl */
460/* ----------------------------------------------------------------- */
461
462static int UwtProcessObjCmdProc(ClientData clientData, Tcl_Interp *interp,
463 int objc, Tcl_Obj *CONST objv[])
464{
465 int size = 0;
466 int i = 0;
467 int level = 0;
468 double value = 0.0;
469 int *input, *noise, *peak, *is_min, *is_max, *is_valid;
470 Tcl_Obj *result = NULL;
471 Tcl_Obj *listnoise = NULL;
472 Tcl_Obj *listpeak = NULL;
473 Tcl_Obj *listmin = NULL;
474 Tcl_Obj *listmax = NULL;
475 Tcl_Obj *listvalid = NULL;
476
477 if(objc != 2)
478 {
479 Tcl_WrongNumArgs(interp, 1, objv, "data");
480 return TCL_ERROR;
481 }
482
483 if(TCL_OK != Tcl_ListObjLength(interp, objv[1], &size))
484 {
485 return TCL_ERROR;
486 }
487
488 input = (int *) malloc(size*sizeof(int));
489 noise = (int *) malloc(size*sizeof(int));
490 peak = (int *) malloc(size*sizeof(int));
491 is_min = (int *) malloc(size*sizeof(int));
492 is_max = (int *) malloc(size*sizeof(int));
493 is_valid = (int *) malloc(size*sizeof(int));
494
495 for(i = 0; i < size; ++i)
496 {
497 Tcl_ListObjIndex(interp, objv[1], i, &result);
498 if(TCL_OK != Tcl_GetDoubleFromObj(interp, result, &value))
499 {
500 free(input);
501 free(noise);
502 free(peak);
503 free(is_min);
504 free(is_max);
505 free(is_valid);
506 return TCL_ERROR;
507 }
508 input[i] = (int) value;
509/*
510 printf("%d -> %g\n", i, input[i]);
511*/
512 }
513
514 uwt_process(input, noise, peak, is_min, is_max, is_valid, size);
515
516 result = Tcl_GetObjResult(interp);
517 listnoise = Tcl_NewObj();
518 listpeak = Tcl_NewObj();
519 listmin = Tcl_NewObj();
520 listmax = Tcl_NewObj();
521 listvalid = Tcl_NewObj();
522 for(i = 0; i < size; ++i)
523 {
524 Tcl_ListObjAppendElement(interp, listnoise, Tcl_NewIntObj(noise[i]));
525 Tcl_ListObjAppendElement(interp, listpeak, Tcl_NewIntObj(peak[i]));
526 Tcl_ListObjAppendElement(interp, listmin, Tcl_NewIntObj(is_min[i]*peak[i]));
527 Tcl_ListObjAppendElement(interp, listmax, Tcl_NewIntObj(is_max[i]*peak[i]));
528 Tcl_ListObjAppendElement(interp, listvalid, Tcl_NewIntObj(is_valid[i]*peak[i]));
529 }
530
531 Tcl_ListObjAppendElement(interp, result, listnoise);
532 Tcl_ListObjAppendElement(interp, result, listpeak);
533 Tcl_ListObjAppendElement(interp, result, listmin);
534 Tcl_ListObjAppendElement(interp, result, listmax);
535 Tcl_ListObjAppendElement(interp, result, listvalid);
536
537 free(input);
538 free(noise);
539 free(peak);
540 free(is_min);
541 free(is_max);
542 free(is_valid);
543
544 return TCL_OK;
545}
546
547/* ----------------------------------------------------------------- */
548
549static int Sum8ObjCmdProc(ClientData clientData, Tcl_Interp *interp,
550 int objc, Tcl_Obj *CONST objv[])
551{
552 int size = 0;
553 int i = 0;
554 int level = 0;
555 double value = 0.0;
556 int *input, *output;
557 Tcl_Obj *result = NULL;
558
559 if(objc != 2)
560 {
561 Tcl_WrongNumArgs(interp, 1, objv, "data");
562 return TCL_ERROR;
563 }
564
565 if(TCL_OK != Tcl_ListObjLength(interp, objv[1], &size))
566 {
567 return TCL_ERROR;
568 }
569
570 input = (int *) malloc(size*sizeof(int));
571 output = (int *) malloc(size*sizeof(int));
572
573 for(i = 0; i < size; ++i)
574 {
575 Tcl_ListObjIndex(interp, objv[1], i, &result);
576 if(TCL_OK != Tcl_GetDoubleFromObj(interp, result, &value))
577 {
578 free(input);
579 free(output);
580 return TCL_ERROR;
581 }
582 input[i] = (int) value;
583/*
584 printf("%d -> %g\n", i, input[i]);
585*/
586 }
587
588 sum8(input, output, size);
589
590 result = Tcl_GetObjResult(interp);
591 for(i = 0; i < size; ++i)
592 {
593 Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(output[i]));
594/*
595 printf("%d -> %g\n", i, d[i]);
596*/
597 }
598
599 free(input);
600 free(output);
601
602 return TCL_OK;
603}
604
605/* ----------------------------------------------------------------- */
606
607static int CsrProcessObjCmdProc(ClientData clientData, Tcl_Interp *interp,
608 int objc, Tcl_Obj *CONST objv[])
609{
610 int size = 0;
611 int i = 0;
612 int level = 0;
613 double value = 0.0;
614 int *input, *noise, *peak, *is_max;
615 Tcl_Obj *result = NULL;
616 Tcl_Obj *listnoise = NULL;
617 Tcl_Obj *listpeak = NULL;
618 Tcl_Obj *listmax = NULL;
619
620 if(objc != 2)
621 {
622 Tcl_WrongNumArgs(interp, 1, objv, "data");
623 return TCL_ERROR;
624 }
625
626 if(TCL_OK != Tcl_ListObjLength(interp, objv[1], &size))
627 {
628 return TCL_ERROR;
629 }
630
631 input = (int *) malloc(size*sizeof(int));
632 noise = (int *) malloc(size*sizeof(int));
633 peak = (int *) malloc(size*sizeof(int));
634 is_max = (int *) malloc(size*sizeof(int));
635
636 for(i = 0; i < size; ++i)
637 {
638 Tcl_ListObjIndex(interp, objv[1], i, &result);
639 if(TCL_OK != Tcl_GetDoubleFromObj(interp, result, &value))
640 {
641 free(input);
642 free(noise);
643 free(peak);
644 free(is_max);
645 return TCL_ERROR;
646 }
647 input[i] = (int) value;
648/*
649 printf("%d -> %g\n", i, input[i]);
650*/
651 }
652
653 csr_process(input, noise, peak, is_max, size);
654
655 result = Tcl_GetObjResult(interp);
656 listnoise = Tcl_NewObj();
657 listpeak = Tcl_NewObj();
658 listmax = Tcl_NewObj();
659 for(i = 0; i < size; ++i)
660 {
661 Tcl_ListObjAppendElement(interp, listnoise, Tcl_NewIntObj(noise[i]));
662 Tcl_ListObjAppendElement(interp, listpeak, Tcl_NewIntObj(peak[i]));
663 Tcl_ListObjAppendElement(interp, listmax, Tcl_NewIntObj(is_max[i]));
664 }
665
666 Tcl_ListObjAppendElement(interp, result, listnoise);
667 Tcl_ListObjAppendElement(interp, result, listpeak);
668 Tcl_ListObjAppendElement(interp, result, listmax);
669
670 free(input);
671 free(noise);
672 free(peak);
673 free(is_max);
674
675 return TCL_OK;
676}
677
678/* ----------------------------------------------------------------- */
679
680int Csr_Init(Tcl_Interp *interp)
681{
682 Tcl_CreateObjCommand(interp, "csr_uwt_process", UwtProcessObjCmdProc, 0, 0);
683 Tcl_CreateObjCommand(interp, "csr_sum8", Sum8ObjCmdProc, 0, 0);
684 Tcl_CreateObjCommand(interp, "csr_process", CsrProcessObjCmdProc, 0, 0);
685
686 return Tcl_PkgProvide(interp, "csr", "0.1");
687}
688
Note: See TracBrowser for help on using the repository browser.