AlcapDAQ  1
caen_compress.cpp
Go to the documentation of this file.
1 //
3 // CAEN TDC compression
4 //
6 
7 #include <stdio.h>
8 
9 #include "midas.h"
10 
11 #include "mucap_compress.h"
12 #include "mucap_structures.h"
13 
18 
20 {
21  huffman_optimize_tree(&caen_channel_huffman);
22  save_huffman("/Compression/Lossless/CAEN/Huffman/Channel", &caen_channel_huffman);
23 }
24 
25 void caen_load()
26 {
27  huffman_init_default(&caen_channel_huffman, 129);
28  load_huffman("/Compression/Lossless/CAEN/Huffman/Channel", &caen_channel_huffman);
29 
30  int size = sizeof(BOOL);
31  db_get_value(hDB, 0, "/Compression/Lossless/CAEN/Enabled", &should_compress_caen,
32  &size, TID_BOOL, TRUE);
33 
34  size = sizeof(BOOL);
35  db_get_value(hDB, 0, "/Compression/Lossless/CAEN/Strip trailing edge",
36  &should_strip_trailing_edge, &size, TID_BOOL, TRUE);
37 
38  size = sizeof(BOOL);
39  db_get_value(hDB, 0, "/Compression/Lossless/CAEN/Strip R1",
40  &should_strip_r1, &size, TID_BOOL, TRUE);
41 }
42 
43 int encode_caen(caen_word * input, int input_size, io_buffer * output,
44  int *uncompressed_size_p)
45 {
46  // Encode CAEN TDC data, which are in the following format:
47  // 0 | channel (7 bits) | Start (1 bit) | 00 | Edge (1 bit) | time (20 bits)
48  //
49  // 1. Optionally, trailing edges are discarded.
50  // 2. An extended channel number, formed from the channel, start,
51  // and edge bits, is Huffman coded.
52  // 3. Successive differences between times are constructed and encoded
53  // with a variable number of bits.
54 
55  int strip_trailing_edge = should_strip_trailing_edge;
56  int strip_r1 = should_strip_r1;
57  int prev_time = 0;
58  int uncompressed_size = 0;
59 
60  io_buffer_put(output, strip_trailing_edge, 1);
61  io_buffer_put(output, strip_r1, 1);
62 
63  for (int i = 0; i < input_size; i++) {
64 
65  int channel = input[i].channel;
66  if (input[i].r2 != 0 || input[i].start) {
67 #if 0
68  printf("in datum %d : r1 %d channel %d start %d r2 %d edge %d time %d\n",
69  i, input[i].r1, input[i].channel, input[i].start, input[i].r2,
70  input[i].edge, input[i].time);
71 #endif
72  channel = 128;
73  } else if (strip_trailing_edge && input[i].edge == 0) {
74  continue;
75  }
76 
77  huffman_put_symbol(&caen_channel_huffman, output, channel);
78 
79  if(channel == 128) {
80  int verbatim = *((int *) &input[i]);
81  io_buffer_put(output, (verbatim >> 16) & 0xffff, 16);
82  io_buffer_put(output, verbatim & 0xffff, 16);
83  } else {
84 
85  if(!strip_r1) {
86  io_buffer_put(output, input[i].r1, 1);
87  }
88 
89  if (!strip_trailing_edge) {
90  io_buffer_put(output, input[i].edge, 1);
91  }
92 
93  int time_diff = input[i].time - prev_time;
94 
95  if (time_diff < 32 && time_diff >= -32) {
96  io_buffer_put(output, 0, 1);
97  io_buffer_put(output, time_diff & 0x3f, 6);
98  } else if (time_diff < 512 && time_diff >= -512) {
99  io_buffer_put(output, 2, 2);
100  io_buffer_put(output, time_diff & 0x3ff, 10);
101  } else {
102  io_buffer_put(output, 3, 2);
103  io_buffer_put(output, time_diff & 0xfffff, 20);
104  }
105 
106  prev_time = input[i].time;
107  }
108 
109  uncompressed_size++;
110  }
111 
112  *uncompressed_size_p = uncompressed_size;
113 
114  return flush_output_buffer(output);
115 }
116 
117 int caen_compress(caen_word * input, int input_size, unsigned char *output, int userParam)
118 {
119  input_size /= sizeof(caen_word);
120 
121  rle_bits_setup();
122 
123  io_buffer output_buffer;
124 
125  // reserve space for size of uncompressed data (may be different from
126  // input size, since some hits may be stripped)
127  int *uncompressed_size_p = (int *) output;
128  output += sizeof(int);
129 
130  // reserve space for the size of the compressed data
131  int *compressed_time_size_p = (int *) output;
132  output += sizeof(int);
133 
134  // compress times
135  start_output_buffer(&output_buffer, output);
136  int compressed_time_size =
137  encode_caen(input, input_size, &output_buffer, uncompressed_size_p);
138  output += compressed_time_size;
139 
140  // store size of compressed times
141  *compressed_time_size_p = compressed_time_size;
142 
143  return compressed_time_size + 2 * sizeof(int);
144 }
145 
146 static int sign_extend(int in, int bits)
147 {
148  int sign_bit = (1 << (bits-1));
149  if(in & sign_bit) {
150  return in | ~(sign_bit - 1);
151  } else {
152  return in;
153  }
154 }
155 
156 void decode_caen(io_buffer * input, caen_word * output)
157 {
158  int strip_trailing_edge = io_buffer_get(input, 1);
159  int strip_r1 = io_buffer_get(input, 1);
160 
161  int prev_time = 0;
162 
163  int i = 0;
164  while (1) {
165 
166  int channel = huffman_get_symbol(&caen_channel_huffman, input);
167 
168  if (channel < 0) {
169  break;
170  }
171 
172  if (channel == 128) {
173  int v1 = io_buffer_get(input, 16);
174  int v2 = io_buffer_get(input, 16);
175 
176  int verbatim = v2 | (v1 << 16);
177  output[i] = *((caen_word *) &verbatim);
178  } else {
179  output[i].start = 0;
180  output[i].channel = channel;
181 
182  if(!strip_r1) {
183  output[i].r1 = io_buffer_get(input, 1);
184  } else {
185  output[i].r1 = 0;
186  }
187  output[i].r2 = 0;
188 
189  if (!strip_trailing_edge) {
190  output[i].edge = io_buffer_get(input, 1);
191  } else {
192  output[i].edge = 1;
193  }
194 
195  int time_length_flag1 = io_buffer_get(input, 1);
196  int time_diff;
197  if (time_length_flag1 == 0) {
198  time_diff = io_buffer_get(input, 6);
199  time_diff = sign_extend(time_diff, 6);
200  } else {
201  int time_length_flag2 = io_buffer_get(input, 1);
202  if (time_length_flag2 == 0) {
203  time_diff = io_buffer_get(input, 10);
204  time_diff = sign_extend(time_diff, 10);
205  } else {
206  time_diff = io_buffer_get(input, 20);
207  time_diff = sign_extend(time_diff, 20);
208  }
209  }
210 
211  output[i].time = (prev_time + time_diff) & 0xfffff;
212  prev_time = output[i].time;
213  }
214 
215  i++;
216  }
217 }
218 
219 int caen_expand(unsigned char *input, int input_size, caen_word * output, int userParam)
220 {
221  //
222  // Uncompress the data produced by caen_compress().
223  //
224 
225  rle_bits_setup();
226 
227  // Get uncompressed data size
228  int *uncompressed_size_p = (int *) input;
229  int uncompressed_size = *uncompressed_size_p;
230  input += sizeof(int);
231  input_size -= sizeof(int);
232 
233  // Get size of compressed time data
234  int *compressed_time_size_p = (int *) input;
235  int compressed_time_size = *compressed_time_size_p;
236  input += sizeof(int);
237  input_size -= sizeof(int);
238 
239  // Uncompress times
240  io_buffer input_buffer;
241  start_input_buffer(&input_buffer, input);
242  decode_caen(&input_buffer, output);
243  input += compressed_time_size;
244  input_size -= compressed_time_size;
245 
246  return uncompressed_size * sizeof(caen_word);
247 }