RocketLogger  2.0.0
rl_file.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2020, ETH Zurich, Computer Engineering Group
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
11  * * Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * * Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <errno.h>
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include <linux/limits.h>
39 #include <time.h>
40 
41 #include "log.h"
42 #include "pru.h"
43 #include "rl.h"
44 #include "rl_file.h"
45 #include "sensor/sensor.h"
46 #include "util.h"
47 
48 #include "rl_file.h"
49 
50 char *RL_UNIT_NAMES[] = {
51  "",
52  "V",
53  "A",
54  "",
55  "",
56  "lx",
57  "C",
58  "",
59  "%",
60  "P",
61  "s",
62 };
63 
71  rl_config_t const *const config);
72 
80 
85 
86 char *rl_unit_to_string(rl_unit_t const unit) {
87  if ((unsigned int)unit <
88  (sizeof(RL_UNIT_NAMES) / sizeof(RL_UNIT_NAMES[0]))) {
89  return RL_UNIT_NAMES[unit];
90  } else {
91  return NULL;
92  }
93 }
94 
95 char *rl_file_get_ambient_file_name(char const *const data_file_name) {
96  static char ambient_file_name[PATH_MAX];
97 
98  // determine new file name
99  strcpy(ambient_file_name, data_file_name);
100 
101  // search for last . character
102  char target = '.';
103  char *file_ending = ambient_file_name;
104  while (strchr(file_ending, target) != NULL) {
105  file_ending = strchr(file_ending, target);
106  file_ending++; // Increment file_ending, otherwise we'll find target at
107  // the same location
108  }
109  file_ending--;
110 
111  // add file ending
112  char ambient_file_ending[PATH_MAX] = RL_FILE_AMBIENT_SUFFIX;
113  strcat(ambient_file_ending, file_ending);
114  strcpy(file_ending, ambient_file_ending);
115 
116  return ambient_file_name;
117 }
118 
120  rl_config_t const *const config) {
121 
122  // number channels
123  uint16_t channel_count = count_channels(config->channel_enable);
124  // number binary channels
125  uint16_t channel_bin_count = 0;
126  if (config->digital_enable) {
127  channel_bin_count = RL_CHANNEL_DIGITAL_COUNT;
128  }
129  if (config->channel_enable[RL_CONFIG_CHANNEL_I1L]) {
130  i1l_valid_channel = channel_bin_count++;
131  }
132  if (config->channel_enable[RL_CONFIG_CHANNEL_I2L]) {
133  i2l_valid_channel = channel_bin_count++;
134  }
135 
136  // comment length
137  uint32_t comment_length = RL_FILE_COMMENT_ALIGNMENT_BYTES;
138 
139  // timestamps
140  rl_timestamp_t timestamp_realtime;
141  rl_timestamp_t timestamp_monotonic;
142  create_time_stamp(&timestamp_realtime, &timestamp_monotonic);
143 
144  // lead_in setup
145  lead_in->file_magic = RL_FILE_MAGIC;
146  lead_in->file_version = RL_FILE_VERSION;
147  lead_in->header_length =
148  sizeof(rl_file_lead_in_t) + comment_length +
149  (channel_count + channel_bin_count) * sizeof(rl_file_channel_t);
150  lead_in->data_block_size = config->sample_rate / config->update_rate;
151  lead_in->data_block_count = 0; // needs to be updated
152  lead_in->sample_count = 0; // needs to be updated
153  lead_in->sample_rate = config->sample_rate;
154  get_mac_addr(lead_in->mac_address);
155  lead_in->start_time = timestamp_realtime;
156  lead_in->comment_length = comment_length;
157  lead_in->channel_bin_count = channel_bin_count;
158  lead_in->channel_count = channel_count;
159 }
160 
162  rl_config_t const *const config) {
163  // number channels
164  uint16_t channel_count = rl_status.sensor_count;
165 
166  // number binary channels
167  uint16_t channel_bin_count = 0;
168 
169  // comment length
170  uint32_t comment_length = RL_FILE_COMMENT_ALIGNMENT_BYTES;
171 
172  // timestamps
173  rl_timestamp_t time_real;
174  rl_timestamp_t time_monotonic;
175  create_time_stamp(&time_real, &time_monotonic);
176 
177  // lead_in setup
178  lead_in->file_magic = RL_FILE_MAGIC;
179  lead_in->file_version = RL_FILE_VERSION;
180  lead_in->header_length =
181  sizeof(rl_file_lead_in_t) + comment_length +
182  (channel_count + channel_bin_count) * sizeof(rl_file_channel_t);
184  lead_in->data_block_count = 0; // needs to be updated
185  lead_in->sample_count = 0; // needs to be updated
186  lead_in->sample_rate =
187  (config->update_rate < RL_SENSOR_SAMPLE_RATE ? config->update_rate
189  get_mac_addr(lead_in->mac_address);
190  lead_in->start_time = time_real;
191  lead_in->comment_length = comment_length;
192  lead_in->channel_bin_count = channel_bin_count;
193  lead_in->channel_count = channel_count;
194 }
195 
197  rl_config_t const *const config) {
198  if (config->file_comment == NULL) {
199  header->comment = "";
200  } else {
201  header->comment = config->file_comment;
202  }
203 
204  rl_file_setup_data_channels(header, config);
205 }
206 
208  rl_config_t const *const config) {
209  if (config->file_comment == NULL) {
210  header->comment = "";
211  } else {
212  header->comment = config->file_comment;
213  }
214 
216 }
217 
218 void rl_file_store_header_bin(FILE *file_handle,
219  rl_file_header_t *const file_header) {
220 
221  int total_channel_count = file_header->lead_in.channel_bin_count +
222  file_header->lead_in.channel_count;
223 
224  // check if alignment bytes are needed after header comment
225  int comment_length = strlen(file_header->comment) + 1;
226  int comment_align_bytes = 0;
227  if (comment_length % RL_FILE_COMMENT_ALIGNMENT_BYTES > 0) {
228  comment_align_bytes =
230  (comment_length % RL_FILE_COMMENT_ALIGNMENT_BYTES);
231  }
232 
233  file_header->lead_in.comment_length = comment_length + comment_align_bytes;
234 
235  file_header->lead_in.header_length =
236  sizeof(rl_file_lead_in_t) + file_header->lead_in.comment_length +
237  total_channel_count * sizeof(rl_file_channel_t);
238 
239  // write lead-in
240  fwrite(&(file_header->lead_in), sizeof(rl_file_lead_in_t), 1, file_handle);
241 
242  // write comment, add zero bytes for proper header alignment if necessary
243  fwrite(file_header->comment, comment_length, 1, file_handle);
244  if (comment_align_bytes > 0) {
245  uint8_t zero_bytes[RL_FILE_COMMENT_ALIGNMENT_BYTES] = {0};
246  fwrite(zero_bytes, comment_align_bytes, 1, file_handle);
247  }
248 
249  // write channel information
250  fwrite(file_header->channel, sizeof(rl_file_channel_t), total_channel_count,
251  file_handle);
252  fflush(file_handle);
253 }
254 
255 void rl_file_store_header_csv(FILE *file_handle,
256  rl_file_header_t const *const file_header) {
257  // lead-in
258  fprintf(file_handle, "RocketLogger CSV File\n");
259  fprintf(file_handle, "File Version,%u\n",
260  (uint32_t)file_header->lead_in.file_version);
261  fprintf(file_handle, "Block Size,%u\n",
262  (uint32_t)file_header->lead_in.data_block_size);
263  fprintf(file_handle, "Block Count,%-20u\n",
264  (uint32_t)file_header->lead_in.data_block_count);
265  fprintf(file_handle, "Sample Count,%-20llu\n",
266  (uint64_t)file_header->lead_in.sample_count);
267  fprintf(file_handle, "Sample Rate,%u\n",
268  (uint32_t)file_header->lead_in.sample_rate);
269  fprintf(file_handle, "MAC Address,%02x",
270  (uint32_t)file_header->lead_in.mac_address[0]);
271 
272  for (int i = 1; i < MAC_ADDRESS_LENGTH; i++) {
273  fprintf(file_handle, ":%02x",
274  (uint32_t)file_header->lead_in.mac_address[i]);
275  }
276  fprintf(file_handle, "\n");
277 
278  time_t time = (time_t)file_header->lead_in.start_time.sec;
279  fprintf(file_handle, "Start Time,%s", ctime(&time));
280  fprintf(file_handle, "Comment,%s\n", file_header->comment);
281  fprintf(file_handle, "\n");
282 
283  // channels
284  for (int i = 0; i < (file_header->lead_in.channel_count +
285  file_header->lead_in.channel_bin_count);
286  i++) {
287  fprintf(file_handle, ",%s", file_header->channel[i].name);
288  switch (file_header->channel[i].channel_scale) {
289  case RL_SCALE_MILLI:
290  fprintf(file_handle, " [m");
291  break;
292  case RL_SCALE_MICRO:
293  fprintf(file_handle, " [u");
294  break;
295  case RL_SCALE_TEN_NANO:
296  fprintf(file_handle, " [10n");
297  break;
298  case RL_SCALE_NANO:
299  fprintf(file_handle, " [n");
300  break;
301  case RL_SCALE_TEN_PICO:
302  fprintf(file_handle, " [10p");
303  break;
304  default:
305  break;
306  }
307  switch (file_header->channel[i].unit) {
308  case RL_UNIT_VOLT:
309  fprintf(file_handle, "V]");
310  break;
311  case RL_UNIT_AMPERE:
312  fprintf(file_handle, "A]");
313  break;
314  case RL_UNIT_SECOND:
315  fprintf(file_handle, "s]");
316  break;
317  default:
318  break;
319  }
320  }
321  fprintf(file_handle, "\n");
322  fflush(file_handle);
323 }
324 
325 void rl_file_update_header_bin(FILE *file_handle,
326  rl_file_header_t const *const file_header) {
327 
328  // seek to beginning and rewrite lead_in
329  rewind(file_handle);
330  fwrite(&(file_header->lead_in), sizeof(rl_file_lead_in_t), 1, file_handle);
331  fflush(file_handle);
332  fseek(file_handle, 0, SEEK_END);
333 }
334 
335 void rl_file_update_header_csv(FILE *file_handle,
336  rl_file_header_t const *const file_header) {
337  rewind(file_handle);
338  fprintf(file_handle, "RocketLogger CSV File\n");
339  fprintf(file_handle, "File Version,%u\n",
340  (uint32_t)file_header->lead_in.file_version);
341  fprintf(file_handle, "Block Size,%u\n",
342  (uint32_t)file_header->lead_in.data_block_size);
343  fprintf(file_handle, "Block Count,%-20u\n",
344  (uint32_t)file_header->lead_in.data_block_count);
345  fprintf(file_handle, "Sample Count,%-20llu\n",
346  (uint64_t)file_header->lead_in.sample_count);
347  fflush(file_handle);
348  fseek(file_handle, 0, SEEK_END);
349 }
350 
351 int rl_file_add_data_block(FILE *data_file, int32_t const *analog_buffer,
352  uint32_t const *digital_buffer, size_t buffer_size,
353  rl_timestamp_t const *const timestamp_realtime,
354  rl_timestamp_t const *const timestamp_monotonic,
355  rl_config_t const *const config) {
356  // aggregation buffer and configuration
357  int32_t aggregate_analog[RL_CHANNEL_COUNT] = {0};
358  uint32_t aggregate_digital = ~(0);
359  ;
360  size_t aggregate_count = RL_SAMPLE_RATE_MIN / config->sample_rate;
361 
362  // skip if not storing to file, or invalid file structure
363  if (!config->file_enable) {
364  return 0;
365  }
366  if (data_file == NULL) {
367  rl_log(RL_LOG_ERROR, "invalid data file provided, skip append data");
368  errno = EINVAL;
369  return ERROR;
370  }
371  if (aggregate_count > buffer_size) {
372  rl_log(RL_LOG_ERROR, "cannot aggregate more data than the buffer size, "
373  "skip append data");
374  errno = EINVAL;
375  return ERROR;
376  }
377 
378  // write buffer timestamp to file
379  if (config->file_format == RL_FILE_FORMAT_RLD) {
380  fwrite(timestamp_realtime, sizeof(rl_timestamp_t), 1, data_file);
381  fwrite(timestamp_monotonic, sizeof(rl_timestamp_t), 1, data_file);
382  } else if (config->file_format == RL_FILE_FORMAT_CSV) {
383  fprintf(data_file, "%lli.%09lli", timestamp_realtime->sec,
384  timestamp_realtime->nsec);
385  }
386 
387  // process data buffers
388  for (size_t i = 0; i < buffer_size; i++) {
389  // point to sample buffer to store by default (updated for aggregates)
390  int32_t const *analog_data = analog_buffer + i * RL_CHANNEL_COUNT;
391  uint32_t const *digital_data = digital_buffer + i;
392 
393  // handle aggregation when applicable
394  if (aggregate_count > 1) {
395  bool aggregate_store = false;
396 
397  // reset aggregate buffer on window start
398  if (i % aggregate_count == 0) {
399  memset(aggregate_analog, 0, sizeof(aggregate_analog));
400  aggregate_digital = ~(0);
401  }
402 
403  switch (config->aggregation_mode) {
405  // store first sample of aggregate window, skip storing others
406  if (i % aggregate_count == 0) {
407  // store data as in non-aggregate mode
408  aggregate_store = true;
409  }
410  break;
411 
413  // accumulate data of the aggregate window, store at the end
414  for (int j = 0; j < RL_CHANNEL_COUNT; j++) {
415  aggregate_analog[j] += *(analog_data + j);
416  }
417  aggregate_digital = aggregate_digital & *digital_data;
418 
419  // on last sample of the window: average analog data and store
420  if ((i + 1) % aggregate_count == 0) {
421  for (int j = 0; j < RL_CHANNEL_COUNT; j++) {
422  aggregate_analog[j] =
423  aggregate_analog[j] / aggregate_count;
424  }
425 
426  // store aggregated data
427  analog_data = (int32_t const *)aggregate_analog;
428  digital_data = (uint32_t const *)aggregate_digital;
429  aggregate_store = true;
430  }
431  break;
432 
433  default:
435  "unknown data aggregation mode, storing all samples.");
436  aggregate_store = true;
437  }
438 
439  // skip storing data if no aggregates available
440  if (!aggregate_store) {
441  continue;
442  }
443  }
444 
445  // write digital channels
446  if (config->file_format == RL_FILE_FORMAT_RLD) {
447  size_t index = 0;
448  uint32_t data = 0x00;
449 
450  // build binary bit field to store
451  if (config->digital_enable) {
452  data |= ((*digital_data & PRU_DIGITAL_INPUT_MASK) << index);
453  index += RL_CHANNEL_DIGITAL_COUNT;
454  }
455  if (config->channel_enable[RL_CONFIG_CHANNEL_I1L]) {
456  if (*digital_data & PRU_DIGITAL_I1L_VALID_MASK) {
457  data |= (1 << index);
458  }
459  index++;
460  }
461  if (config->channel_enable[RL_CONFIG_CHANNEL_I2L]) {
462  if (*digital_data & PRU_DIGITAL_I2L_VALID_MASK) {
463  data |= (1 << index);
464  }
465  index++;
466  }
467 
468  // write digital data to file
469  fwrite(&data, sizeof(data), 1, data_file);
470  } else if (config->file_format == RL_FILE_FORMAT_CSV) {
471  if (config->digital_enable) {
472  uint32_t binary_mask = PRU_DIGITAL_INPUT1_MASK;
473  for (int j = 0; j < RL_CHANNEL_DIGITAL_COUNT; j++) {
474  fprintf(data_file, (RL_FILE_CSV_DELIMITER "%i"),
475  (*digital_data & binary_mask) > 0);
476  binary_mask = binary_mask << 1;
477  }
478  }
479  if (config->channel_enable[RL_CONFIG_CHANNEL_I1L]) {
480  fprintf(data_file, (RL_FILE_CSV_DELIMITER "%i"),
481  (*digital_data & PRU_DIGITAL_I1L_VALID_MASK) > 0);
482  }
483  if (config->channel_enable[RL_CONFIG_CHANNEL_I2L]) {
484  fprintf(data_file, (RL_FILE_CSV_DELIMITER "%i"),
485  (*digital_data & PRU_DIGITAL_I2L_VALID_MASK) > 0);
486  }
487  }
488 
489  // write analog channels
490  for (int j = 0; j < RL_CHANNEL_COUNT; j++) {
491  // skip disabled channels
492  if (!config->channel_enable[j]) {
493  continue;
494  }
495  // write analog data to file
496  if (config->file_format == RL_FILE_FORMAT_RLD) {
497  fwrite(&analog_data[j], sizeof(int32_t), 1, data_file);
498  } else if (config->file_format == RL_FILE_FORMAT_CSV) {
499  fprintf(data_file, (RL_FILE_CSV_DELIMITER "%d"),
500  analog_data[j]);
501  }
502  }
503 
504  // end of data row
505  if (config->file_format == RL_FILE_FORMAT_CSV) {
506  fprintf(data_file, "\n");
507  }
508  }
509 
510  // flush processed data if data is stored
511  if (config->file_enable && data_file != NULL) {
512  fflush(data_file);
513  }
514 
515  return 1;
516 }
517 
518 int rl_file_add_ambient_block(FILE *ambient_file, int32_t const *ambient_buffer,
519  size_t buffer_size,
520  rl_timestamp_t const *const timestamp_realtime,
521  rl_timestamp_t const *const timestamp_monotonic,
522  rl_config_t const *const config) {
523  // suppress unused parameter warning
524  (void)config;
525 
526  // store timestamps
527  fwrite(timestamp_realtime, sizeof(rl_timestamp_t), 1, ambient_file);
528  fwrite(timestamp_monotonic, sizeof(rl_timestamp_t), 1, ambient_file);
529 
530  // store sensor data
531  fwrite(ambient_buffer, sizeof(int32_t), buffer_size, ambient_file);
532 
533  return 1;
534 }
535 
537  rl_config_t const *const config) {
538  int total_channel_count = file_header->lead_in.channel_bin_count +
539  file_header->lead_in.channel_count;
540 
541  // reset channels
542  memset(file_header->channel, 0,
543  total_channel_count * sizeof(rl_file_channel_t));
544 
545  // overall channel index
546  int ch = 0;
547 
548  // digital channels
549  if (config->digital_enable) {
550  for (int i = 0; i < RL_CHANNEL_DIGITAL_COUNT; i++) {
551  file_header->channel[ch].unit = RL_UNIT_BINARY;
552  file_header->channel[ch].channel_scale = RL_SCALE_UNIT;
553  file_header->channel[ch].data_size = 0;
554  file_header->channel[ch].valid_data_channel =
556  strcpy(file_header->channel[ch].name, RL_CHANNEL_DIGITAL_NAMES[i]);
557  ch++;
558  }
559  }
560 
561  // range valid channels
562  if (config->channel_enable[RL_CONFIG_CHANNEL_I1L]) {
563  file_header->channel[ch].unit = RL_UNIT_RANGE_VALID;
564  file_header->channel[ch].channel_scale = RL_SCALE_UNIT;
565  file_header->channel[ch].data_size = 0;
567  strcpy(file_header->channel[ch].name, RL_CHANNEL_VALID_NAMES[0]);
568  ch++;
569  }
570  if (config->channel_enable[RL_CONFIG_CHANNEL_I2L]) {
571  file_header->channel[ch].unit = RL_UNIT_RANGE_VALID;
572  file_header->channel[ch].channel_scale = RL_SCALE_UNIT;
573  file_header->channel[ch].data_size = 0;
575  strcpy(file_header->channel[ch].name, RL_CHANNEL_VALID_NAMES[1]);
576  ch++;
577  }
578 
579  // analog channels
580  for (int i = 0; i < RL_CHANNEL_COUNT; i++) {
581  if (config->channel_enable[i]) {
582  if (is_current(i)) {
583  if (is_low_current(i)) {
584  file_header->channel[ch].channel_scale = RL_SCALE_TEN_PICO;
585  if (i == RL_CONFIG_CHANNEL_I1L) {
586  file_header->channel[ch].valid_data_channel =
588  } else {
589  file_header->channel[ch].valid_data_channel =
591  }
592  } else {
593  file_header->channel[ch].channel_scale = RL_SCALE_NANO;
594  file_header->channel[ch].valid_data_channel =
596  }
597  file_header->channel[ch].unit = RL_UNIT_AMPERE;
598  } else if (is_voltage(i)) {
599  file_header->channel[ch].unit = RL_UNIT_VOLT;
600  file_header->channel[ch].channel_scale = RL_SCALE_TEN_NANO;
601  file_header->channel[ch].valid_data_channel =
603  } else {
604  file_header->channel[ch].unit = RL_UNIT_SECOND;
605  file_header->channel[ch].channel_scale = RL_SCALE_NANO;
606  file_header->channel[ch].valid_data_channel =
608  }
609  // if calibration measurement, set unit to undefined
610  if (config->calibration_ignore) {
611  file_header->channel[ch].unit = RL_UNIT_UNDEFINED;
612  file_header->channel[ch].channel_scale = RL_SCALE_UNIT;
613  }
614  file_header->channel[ch].data_size = 4;
615  strncpy(file_header->channel[ch].name, RL_CHANNEL_NAMES[i],
617  ch++;
618  }
619  }
620 }
621 
623  int total_channel_count =
625 
626  // reset channels
627  memset(header->channel, 0, total_channel_count * sizeof(rl_file_channel_t));
628 
629  // write channels
630  int ch = 0;
631  for (int i = 0; i < SENSOR_REGISTRY_SIZE; i++) {
632  if (rl_status.sensor_available[i]) {
633  header->channel[ch].unit = SENSOR_REGISTRY[i].unit;
634  header->channel[ch].channel_scale = SENSOR_REGISTRY[i].scale;
636  header->channel[ch].data_size = 4;
637  strcpy(header->channel[ch].name, SENSOR_REGISTRY[i].name);
638  ch++;
639  }
640  }
641 }
rl_calibration_t data
The actual calibration data.
Definition: calibration.h:9
int rl_log(rl_log_level_t log_level, char const *const format,...)
Definition: log.c:82
@ RL_LOG_ERROR
Error.
Definition: log.h:49
@ RL_LOG_WARNING
Warning.
Definition: log.h:50
#define PRU_DIGITAL_INPUT1_MASK
Definition: pru.h:54
#define PRU_DIGITAL_I1L_VALID_MASK
Definition: pru.h:60
#define PRU_DIGITAL_I2L_VALID_MASK
Definition: pru.h:61
#define PRU_DIGITAL_INPUT_MASK
Definition: pru.h:53
char const *const RL_CHANNEL_NAMES[RL_CHANNEL_COUNT]
RocketLogger channel names.
Definition: rl.c:95
char const *const RL_CHANNEL_VALID_NAMES[RL_CHANNEL_SWITCHED_COUNT]
RocketLogger valid channel names.
Definition: rl.c:107
char const *const RL_CHANNEL_DIGITAL_NAMES[RL_CHANNEL_DIGITAL_COUNT]
RocketLogger digital channel names.
Definition: rl.c:103
#define RL_CONFIG_CHANNEL_I2L
Definition: rl.h:89
@ RL_FILE_FORMAT_RLD
CSV format.
Definition: rl.h:143
@ RL_FILE_FORMAT_CSV
Definition: rl.h:142
#define RL_SENSOR_SAMPLE_RATE
Ambient sensor read out rate in samples per second.
Definition: rl.h:66
#define RL_SAMPLE_RATE_MIN
Minimum native sample rate of the ADC in samples per second.
Definition: rl.h:62
#define ERROR
Function return value for errors (use errno to indicate the error)
Definition: rl.h:46
#define RL_CHANNEL_DIGITAL_COUNT
Number of RocketLogger digital channels.
Definition: rl.h:60
#define RL_CONFIG_CHANNEL_I1L
Definition: rl.h:87
#define RL_CHANNEL_COUNT
Number of RocketLogger analog channels.
Definition: rl.h:56
@ RL_AGGREGATION_MODE_AVERAGE
Aggregate using down sampling.
Definition: rl.h:130
@ RL_AGGREGATION_MODE_DOWNSAMPLE
Definition: rl.h:129
char * rl_unit_to_string(rl_unit_t const unit)
Definition: rl_file.c:86
void rl_file_store_header_bin(FILE *file_handle, rl_file_header_t *const file_header)
Definition: rl_file.c:218
int i1l_valid_channel
Global variable to determine i1l valid channel index.
Definition: rl_file.c:82
void rl_file_update_header_bin(FILE *file_handle, rl_file_header_t const *const file_header)
Definition: rl_file.c:325
int i2l_valid_channel
Global variable to determine i2l valid channel index.
Definition: rl_file.c:84
int rl_file_add_data_block(FILE *data_file, int32_t const *analog_buffer, uint32_t const *digital_buffer, size_t buffer_size, rl_timestamp_t const *const timestamp_realtime, rl_timestamp_t const *const timestamp_monotonic, rl_config_t const *const config)
Definition: rl_file.c:351
char * RL_UNIT_NAMES[]
Definition: rl_file.c:50
void rl_file_store_header_csv(FILE *file_handle, rl_file_header_t const *const file_header)
Definition: rl_file.c:255
void rl_file_setup_data_channels(rl_file_header_t *const header, rl_config_t const *const config)
Definition: rl_file.c:536
void rl_file_setup_ambient_lead_in(rl_file_lead_in_t *const lead_in, rl_config_t const *const config)
Definition: rl_file.c:161
void rl_file_setup_ambient_header(rl_file_header_t *const header, rl_config_t const *const config)
Definition: rl_file.c:207
void rl_file_update_header_csv(FILE *file_handle, rl_file_header_t const *const file_header)
Definition: rl_file.c:335
int rl_file_add_ambient_block(FILE *ambient_file, int32_t const *ambient_buffer, size_t buffer_size, rl_timestamp_t const *const timestamp_realtime, rl_timestamp_t const *const timestamp_monotonic, rl_config_t const *const config)
Definition: rl_file.c:518
void rl_file_setup_data_header(rl_file_header_t *const header, rl_config_t const *const config)
Definition: rl_file.c:196
char * rl_file_get_ambient_file_name(char const *const data_file_name)
Definition: rl_file.c:95
void rl_file_setup_ambient_channels(rl_file_header_t *const header)
Definition: rl_file.c:622
void rl_file_setup_data_lead_in(rl_file_lead_in_t *const lead_in, rl_config_t const *const config)
Definition: rl_file.c:119
@ RL_UNIT_VOLT
Voltage (electric)
Definition: rl_file.h:87
@ RL_UNIT_UNDEFINED
Undefined unit.
Definition: rl_file.h:97
@ RL_UNIT_AMPERE
Current (electric)
Definition: rl_file.h:88
@ RL_UNIT_BINARY
Binary signal.
Definition: rl_file.h:89
@ RL_UNIT_RANGE_VALID
Range valid information.
Definition: rl_file.h:90
@ RL_UNIT_SECOND
Second (time delta)
Definition: rl_file.h:96
enum rl_unit rl_unit_t
Definition: rl_file.h:103
#define RL_FILE_COMMENT_ALIGNMENT_BYTES
Comment alignment in bytes.
Definition: rl_file.h:56
#define RL_SCALE_MICRO
Definition: rl_file.h:74
#define RL_SCALE_TEN_NANO
Definition: rl_file.h:73
#define RL_FILE_VERSION
File format version of current implementation.
Definition: rl_file.h:47
#define RL_SCALE_NANO
Definition: rl_file.h:72
#define RL_SCALE_MILLI
Definition: rl_file.h:75
#define RL_SCALE_TEN_PICO
Definition: rl_file.h:71
#define RL_SCALE_UNIT
Definition: rl_file.h:76
#define RL_FILE_AMBIENT_DATA_BLOCK_SIZE
Ambient sensor data file block size in measurements.
Definition: rl_file.h:65
struct rl_file_lead_in rl_file_lead_in_t
Definition: rl_file.h:138
#define RL_FILE_CHANNEL_NAME_LENGTH
Maximum channel description length.
Definition: rl_file.h:50
#define RL_FILE_AMBIENT_SUFFIX
Ambient sensor data file name suffix.
Definition: rl_file.h:62
#define RL_FILE_MAGIC
File header magic number (ascii RLD)
Definition: rl_file.h:44
#define RL_FILE_CHANNEL_NO_LINK
No additional range valid information available.
Definition: rl_file.h:53
#define RL_FILE_CSV_DELIMITER
CSV value delimiter character.
Definition: rl_file.h:59
struct rl_file_channel rl_file_channel_t
Definition: rl_file.h:159
const rl_sensor_t SENSOR_REGISTRY[SENSOR_REGISTRY_SIZE]
Definition: sensor.c:63
#define SENSOR_REGISTRY_SIZE
Number of sensor registered.
Definition: sensor.h:47
Definition: rl.h:154
char const * file_comment
File comment.
Definition: rl.h:190
rl_aggregation_mode_t aggregation_mode
Sample aggregation mode (for sampling rates below lowest native one)
Definition: rl.h:172
rl_file_format_t file_format
File format.
Definition: rl.h:186
uint32_t sample_rate
Sampling rate.
Definition: rl.h:164
bool channel_enable[RL_CHANNEL_COUNT]
Channels to sample.
Definition: rl.h:168
uint32_t update_rate
Data update rate.
Definition: rl.h:166
bool file_enable
Enable storing measurements to file.
Definition: rl.h:182
bool digital_enable
Enable digital inputs.
Definition: rl.h:174
bool calibration_ignore
Perform calibration measurement (ignore existing calibration)
Definition: rl.h:178
char name[RL_FILE_CHANNEL_NAME_LENGTH]
Channel name/description.
Definition: rl_file.h:153
uint16_t data_size
Datum size in bytes (for voltage and current)
Definition: rl_file.h:149
rl_unit_t unit
Channel unit.
Definition: rl_file.h:145
int32_t channel_scale
Channel scale (in power of ten, for voltage and current)
Definition: rl_file.h:147
uint16_t valid_data_channel
Link to channel valid data (for low-range current channels)
Definition: rl_file.h:151
rl_file_channel_t * channel
Channels definitions (binary and normal)
Definition: rl_file.h:170
rl_file_lead_in_t lead_in
File header lead in (constant size)
Definition: rl_file.h:166
char const * comment
Comment field.
Definition: rl_file.h:168
uint32_t comment_length
Comment length.
Definition: rl_file.h:128
uint16_t sample_rate
Sampling rate of the measurement.
Definition: rl_file.h:122
uint16_t file_version
File version number.
Definition: rl_file.h:112
rl_timestamp_t start_time
Start time of the measurement in UNIX time, UTC.
Definition: rl_file.h:126
uint64_t sample_count
Total sample count.
Definition: rl_file.h:120
uint8_t mac_address[MAC_ADDRESS_LENGTH]
Instrument ID (mac address)
Definition: rl_file.h:124
uint16_t channel_count
Analog channel count.
Definition: rl_file.h:132
uint32_t data_block_count
Number of data blocks stored in the file.
Definition: rl_file.h:118
uint32_t data_block_size
Size of the data blocks in the file in rows.
Definition: rl_file.h:116
uint16_t header_length
Total size of the header in bytes.
Definition: rl_file.h:114
uint32_t file_magic
File magic constant.
Definition: rl_file.h:110
uint16_t channel_bin_count
Binary channel count.
Definition: rl_file.h:130
int32_t scale
Definition: sensor.h:59
rl_unit_t unit
Definition: sensor.h:58
char name[SENSOR_NAME_LENGTH]
Definition: sensor.h:55
Definition: rl.h:201
uint16_t sensor_count
Number of sensors found connected to the system.
Definition: rl.h:221
bool sensor_available[RL_SENSOR_COUNT_MAX]
Identifiers of sensors found.
Definition: rl.h:223
int64_t nsec
Nanoseconds.
Definition: util.h:53
int64_t sec
Seconds in UNIX time (UTC)
Definition: util.h:51
bool is_current(int index)
Definition: util.c:49
int count_channels(bool const channels[RL_CHANNEL_COUNT])
Definition: util.c:72
void create_time_stamp(rl_timestamp_t *const timestamp_realtime, rl_timestamp_t *const timestamp_monotonic)
Definition: util.c:90
void get_mac_addr(uint8_t mac_address[MAC_ADDRESS_LENGTH])
Definition: util.c:112
bool is_low_current(int index)
Definition: util.c:57
bool is_voltage(int index)
Definition: util.c:64
#define MAC_ADDRESS_LENGTH
MAC address length in bytes.
Definition: util.h:41