AlcapDAQ  1
tdc400_compress.cpp
Go to the documentation of this file.
1 //
3 // Run-length encoding and decoding of times.
4 //
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 
10 #include "midas.h"
11 
12 #include "mucap_compress.h"
13 #include "mucap_structures.h"
14 
18 
20 {
21  huffman_optimize_tree(&time_huffman);
22  huffman_optimize_tree(&bits_huffman[0]);
23  huffman_optimize_tree(&bits_huffman[1]);
24 
25  save_huffman("/Compression/Lossless/TDC400/Huffman/Time", &time_huffman);
26  save_huffman("/Compression/Lossless/TDC400/Huffman/Bits 0", &bits_huffman[0]);
27  save_huffman("/Compression/Lossless/TDC400/Huffman/Bits 1", &bits_huffman[1]);
28 }
29 
31 {
32  huffman_init_default(&time_huffman, 128);
33  huffman_init_default(&bits_huffman[0], 128);
34  huffman_init_default(&bits_huffman[1], 128);
35 
36  load_huffman("/Compression/Lossless/TDC400/Huffman/Time", &time_huffman);
37  load_huffman("/Compression/Lossless/TDC400/Huffman/Bits 0", &bits_huffman[0]);
38  load_huffman("/Compression/Lossless/TDC400/Huffman/Bits 1", &bits_huffman[1]);
39 
40  int size = sizeof(BOOL);
41  db_get_value(hDB, 0, "/Compression/Lossless/TDC400/Enabled", &should_compress_tdc400,
42  &size, TID_BOOL, TRUE);
43 }
44 
45 void binary_print(unsigned char c)
46 {
47  for (int i = 0; i < 8; i++) {
48  if (c & 0x80) {
49  printf("X");
50  } else {
51  printf(".");
52  }
53 
54  c = c << 1;
55  }
56 }
57 
58 void event_display(tdc400_word * input, int length)
59 {
60  for (int i = 0; i < length; i++) {
61  printf("%d ", input[i].time);
62 
63  for (int j = 0; j < 6; j++) {
64  binary_print(tdc400_byte(input[i], j));
65  printf(" ");
66  }
67 
68  printf("\n");
69  }
70 
71  printf("------------------------------------------------------------\n");
72 }
73 
74 int encode_times(tdc400_word * input, int input_size, io_buffer * output)
75 {
76  //
77  // Perform a variant of run-length encoding on the times in the TDC400
78  // data, which are the most significant 16 bits in every 64 bit word.
79  //
80  // Times typically come in blocks of consecutive words, where the
81  // block
82  // length is generally of order 20. We will store the time of the
83  // start of the block followed by the number of elements in the block.
84  //
85  // More precisely, this is what we do:
86  // - Take the difference of the first time of the current block
87  // from the first time of the previous block.
88  // - If the difference is less than 256, store a 0; otherwise, store a 1
89  //
90  // - Store either 8 or 16 bits of time difference information.
91  // - Store Huffman-coded run length.
92  //
93 
94  int run_length = 1;
95  unsigned short prev_time = 0;
96  unsigned short prev_run_time = 0;
97 
98  for (int i = 0; i < input_size; i++) {
99  unsigned short this_time = input[i].time;
100 
101  if (this_time == prev_time + 1 && i != 0 && run_length < 127) {
102  run_length++;
103  } else {
104  if (i != 0) {
105 #if 0
106  if (run_length >= 8) {
107  event_display(&input[i - run_length], run_length);
108  }
109 #endif
110  huffman_put_symbol(&time_huffman, output, run_length);
111  }
112  run_length = 1;
113 
114  unsigned short this_run_time_diff = this_time - prev_run_time;
115  if (this_run_time_diff < 256) {
116  io_buffer_put(output, this_run_time_diff, 9);
117  } else {
118  io_buffer_put(output, 0x00010000 | this_run_time_diff, 17);
119  }
120  output->num_codes++;
121 
122  prev_run_time = this_time;
123  }
124 
125  prev_time = this_time;
126  }
127 
128  huffman_put_symbol(&time_huffman, output, run_length);
129 
130  return flush_output_buffer(output);
131 }
132 
133 void decode_times(io_buffer * input, tdc400_word * output)
134 {
135  //
136  // Reverse the encoding performed by encode_times.
137  //
138 
139  int num_words_in = input->num_codes / 2;
140  int output_size = 0;
141  unsigned short prev_run_time = 0;
142 
143  for (int i = 0; i < num_words_in; i++) {
144  int first_time_length_flag = io_buffer_get(input, 1);
145  unsigned short first_time;
146  if (first_time_length_flag) {
147  first_time = io_buffer_get(input, 16);
148  } else {
149  first_time = io_buffer_get(input, 8);
150  }
151 
152  int run_length = huffman_get_symbol(&time_huffman, input);
153 
154  for (int j = 0; j < run_length; j++) {
155  output[output_size++].time = first_time + prev_run_time + j;
156  }
157 
158  prev_run_time += first_time;
159  }
160 }
161 
162 int encode_bits(tdc400_word * input, int input_size, io_buffer * output)
163 {
164  //
165  // Perform bitwise run-length encoding on the bit mask portion of
166  // the TDC400 data. For example, the following bit pattern:
167  //
168  // t 000000000011100000000000000000000000000000000000
169  // t+1 000000000000110000000000000000000000000000000000
170  //
171  // which is not altogether improbable, would be encoded as
172  //
173  // 10, 3, 47, 2, 34
174  //
175  // Then, store Huffman codes for the run lengths. Use a separate
176  // Huffman table for the "zero" runs and the "one" runs.
177  //
178 
179  rle_state s = { 0, 0, {128, 128}, 0, bits_huffman };
180 
181  for (int i = 0; i < input_size; i++) {
182  for (int j = 0; j < 6; j++) {
183  unsigned char b = tdc400_byte(input[i], j);
184  rle_put(b, &s, output);
185  }
186  }
187 
188  return flush_rle(&s, output);
189 }
190 
191 void decode_bits(io_buffer * input, tdc400_word * output, int output_size)
192 {
193  rle_state s = { 1, 0, {128, 128}, 0, bits_huffman };
194 
195  for (int i = 0; i < output_size; i++) {
196  for (int j = 0; j < 6; j++) {
197  int b = rle_get(input, &s);
198  if (b >= 0) {
199  tdc400_byte(output[i], j) = (unsigned char) b;
200  } else {
201  return;
202  }
203  }
204  }
205 }
206 
207 int tdc400_compress(tdc400_word * input, int input_size,
208  unsigned char *output, int userParam)
209 {
210  //
211  // Carry out lossless compression on the TPC data recorded by a
212  // single TDC400.
213  //
214 
215  input_size /= sizeof(tdc400_word);
216 
217  rle_bits_setup();
218 
219  io_buffer output_buffer;
220 
221  // store size of input data
222  int *uncompressed_size_p = (int *) output;
223  *uncompressed_size_p = input_size;
224  output += sizeof(int);
225 
226  // reserve space for the size of the compressed times
227  int *compressed_time_size_p = (int *) output;
228  output += sizeof(int);
229 
230  // compress times
231  start_output_buffer(&output_buffer, output);
232  int compressed_time_size =
233  encode_times(input, input_size, &output_buffer);
234  output += compressed_time_size;
235 
236  // store size of compressed times
237  *compressed_time_size_p = compressed_time_size;
238 
239  // reserve space for the size of the compressed bit patterns
240  int *compressed_bits_size_p = (int *) output;
241  output += sizeof(int);
242 
243  // compress bit patterns
244  start_output_buffer(&output_buffer, output);
245  int compressed_bits_size =
246  encode_bits(input, input_size, &output_buffer);
247  output += compressed_time_size;
248 
249  // store size of compressed bit patterns
250  *compressed_bits_size_p = compressed_bits_size;
251 
252  return compressed_time_size + compressed_bits_size + 3 * sizeof(int);
253 }
254 
255 int tdc400_expand(unsigned char *input, int input_size,
256  tdc400_word * output, int userParam)
257 {
258  //
259  // Uncompress the data produced by tdc400_compress().
260  //
261 
262  rle_bits_setup();
263 
264  // Get uncompressed data size
265  int *uncompressed_size_p = (int *) input;
266  int uncompressed_size = *uncompressed_size_p;
267  input += sizeof(int);
268  input_size -= sizeof(int);
269 
270  // Get size of compressed time data
271  int *compressed_time_size_p = (int *) input;
272  int compressed_time_size = *compressed_time_size_p;
273  input += sizeof(int);
274  input_size -= sizeof(int);
275 
276  // Uncompress times
277  io_buffer input_buffer;
278  start_input_buffer(&input_buffer, input);
279  decode_times(&input_buffer, output);
280  input += compressed_time_size;
281  input_size -= compressed_time_size;
282 
283  // Get size of compressed bit patterns
284  int *compressed_bits_size_p = (int *) input;
285  int compressed_bits_size = *compressed_bits_size_p;
286  input += sizeof(int);
287  input_size -= sizeof(int);
288 
289  // Uncompress bit patterns
290  start_input_buffer(&input_buffer, input);
291  decode_bits(&input_buffer, output, uncompressed_size);
292 
293  return uncompressed_size * sizeof(tdc400_word);
294 }
295