RocketLogger  2.0.1
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  int64_t aggregate_analog_sum[RL_CHANNEL_COUNT] = {0};
359  uint32_t aggregate_digital = ~((uint32_t)0);
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_sum, 0, sizeof(aggregate_analog_sum));
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 when window complete
414  for (int j = 0; j < RL_CHANNEL_COUNT; j++) {
415  aggregate_analog_sum[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  // calculate aggregated data block
422  for (int j = 0; j < RL_CHANNEL_COUNT; j++) {
423  aggregate_analog[j] =
424  aggregate_analog_sum[j] / aggregate_count;
425  }
426 
427  // store aggregated data
428  analog_data = aggregate_analog;
429  digital_data = &aggregate_digital;
430  aggregate_store = true;
431  }
432  break;
433 
434  default:
436  "unknown data aggregation mode, storing all samples.");
437  aggregate_store = true;
438  }
439 
440  // skip storing data if no aggregates available
441  if (!aggregate_store) {
442  continue;
443  }
444  }
445 
446  // write digital channels
447  if (config->file_format == RL_FILE_FORMAT_RLD) {
448  size_t index = 0;
449  uint32_t data = 0x00;
450 
451  // build binary bit field to store
452  if (config->digital_enable) {
453  data |= ((*digital_data & PRU_DIGITAL_INPUT_MASK) << index);
454  index += RL_CHANNEL_DIGITAL_COUNT;
455  }
456  if (config->channel_enable[RL_CONFIG_CHANNEL_I1L]) {
457  if (*digital_data & PRU_DIGITAL_I1L_VALID_MASK) {
458  data |= (1 << index);
459  }
460  index++;
461  }
462  if (config->channel_enable[RL_CONFIG_CHANNEL_I2L]) {
463  if (*digital_data & PRU_DIGITAL_I2L_VALID_MASK) {
464  data |= (1 << index);
465  }
466  index++;
467  }
468 
469  // write digital data to file
470  fwrite(&data, sizeof(data), 1, data_file);
471  } else if (config->file_format == RL_FILE_FORMAT_CSV) {
472  if (config->digital_enable) {
473  uint32_t binary_mask = PRU_DIGITAL_INPUT1_MASK;
474  for (int j = 0; j < RL_CHANNEL_DIGITAL_COUNT; j++) {
475  fprintf(data_file, (RL_FILE_CSV_DELIMITER "%i"),
476  (*digital_data & binary_mask) > 0);
477  binary_mask = binary_mask << 1;
478  }
479  }
480  if (config->channel_enable[RL_CONFIG_CHANNEL_I1L]) {
481  fprintf(data_file, (RL_FILE_CSV_DELIMITER "%i"),
482  (*digital_data & PRU_DIGITAL_I1L_VALID_MASK) > 0);
483  }
484  if (config->channel_enable[RL_CONFIG_CHANNEL_I2L]) {
485  fprintf(data_file, (RL_FILE_CSV_DELIMITER "%i"),
486  (*digital_data & PRU_DIGITAL_I2L_VALID_MASK) > 0);
487  }
488  }
489 
490  // write analog channels
491  for (int j = 0; j < RL_CHANNEL_COUNT; j++) {
492  // skip disabled channels
493  if (!config->channel_enable[j]) {
494  continue;
495  }
496  // write analog data to file
497  if (config->file_format == RL_FILE_FORMAT_RLD) {
498  fwrite(&analog_data[j], sizeof(int32_t), 1, data_file);
499  } else if (config->file_format == RL_FILE_FORMAT_CSV) {
500  fprintf(data_file, (RL_FILE_CSV_DELIMITER "%d"),
501  analog_data[j]);
502  }
503  }
504 
505  // end of data row
506  if (config->file_format == RL_FILE_FORMAT_CSV) {
507  fprintf(data_file, "\n");
508  }
509  }
510 
511  // flush processed data if data is stored
512  if (config->file_enable && data_file != NULL) {
513  fflush(data_file);
514  }
515 
516  return 1;
517 }
518 
519 int rl_file_add_ambient_block(FILE *ambient_file, int32_t const *ambient_buffer,
520  size_t buffer_size,
521  rl_timestamp_t const *const timestamp_realtime,
522  rl_timestamp_t const *const timestamp_monotonic,
523  rl_config_t const *const config) {
524  // suppress unused parameter warning
525  (void)config;
526 
527  // store timestamps
528  fwrite(timestamp_realtime, sizeof(rl_timestamp_t), 1, ambient_file);
529  fwrite(timestamp_monotonic, sizeof(rl_timestamp_t), 1, ambient_file);
530 
531  // store sensor data
532  fwrite(ambient_buffer, sizeof(int32_t), buffer_size, ambient_file);
533 
534  return 1;
535 }
536 
538  rl_config_t const *const config) {
539  int total_channel_count = file_header->lead_in.channel_bin_count +
540  file_header->lead_in.channel_count;
541 
542  // reset channels
543  memset(file_header->channel, 0,
544  total_channel_count * sizeof(rl_file_channel_t));
545 
546  // overall channel index
547  int ch = 0;
548 
549  // digital channels
550  if (config->digital_enable) {
551  for (int i = 0; i < RL_CHANNEL_DIGITAL_COUNT; i++) {
552  file_header->channel[ch].unit = RL_UNIT_BINARY;
553  file_header->channel[ch].channel_scale = RL_SCALE_UNIT;
554  file_header->channel[ch].data_size = 0;
555  file_header->channel[ch].valid_data_channel =
557  strcpy(file_header->channel[ch].name, RL_CHANNEL_DIGITAL_NAMES[i]);
558  ch++;
559  }
560  }
561 
562  // range valid channels
563  if (config->channel_enable[RL_CONFIG_CHANNEL_I1L]) {
564  file_header->channel[ch].unit = RL_UNIT_RANGE_VALID;
565  file_header->channel[ch].channel_scale = RL_SCALE_UNIT;
566  file_header->channel[ch].data_size = 0;
568  strcpy(file_header->channel[ch].name, RL_CHANNEL_VALID_NAMES[0]);
569  ch++;
570  }
571  if (config->channel_enable[RL_CONFIG_CHANNEL_I2L]) {
572  file_header->channel[ch].unit = RL_UNIT_RANGE_VALID;
573  file_header->channel[ch].channel_scale = RL_SCALE_UNIT;
574  file_header->channel[ch].data_size = 0;
576  strcpy(file_header->channel[ch].name, RL_CHANNEL_VALID_NAMES[1]);
577  ch++;
578  }
579 
580  // analog channels
581  for (int i = 0; i < RL_CHANNEL_COUNT; i++) {
582  if (config->channel_enable[i]) {
583  if (is_current(i)) {
584  if (is_low_current(i)) {
585  file_header->channel[ch].channel_scale = RL_SCALE_TEN_PICO;
586  if (i == RL_CONFIG_CHANNEL_I1L) {
587  file_header->channel[ch].valid_data_channel =
589  } else {
590  file_header->channel[ch].valid_data_channel =
592  }
593  } else {
594  file_header->channel[ch].channel_scale = RL_SCALE_NANO;
595  file_header->channel[ch].valid_data_channel =
597  }
598  file_header->channel[ch].unit = RL_UNIT_AMPERE;
599  } else if (is_voltage(i)) {
600  file_header->channel[ch].unit = RL_UNIT_VOLT;
601  file_header->channel[ch].channel_scale = RL_SCALE_TEN_NANO;
602  file_header->channel[ch].valid_data_channel =
604  } else {
605  file_header->channel[ch].unit = RL_UNIT_SECOND;
606  file_header->channel[ch].channel_scale = RL_SCALE_NANO;
607  file_header->channel[ch].valid_data_channel =
609  }
610  // if calibration measurement, set unit to undefined
611  if (config->calibration_ignore) {
612  file_header->channel[ch].unit = RL_UNIT_UNDEFINED;
613  file_header->channel[ch].channel_scale = RL_SCALE_UNIT;
614  }
615  file_header->channel[ch].data_size = 4;
616  strncpy(file_header->channel[ch].name, RL_CHANNEL_NAMES[i],
618  ch++;
619  }
620  }
621 }
622 
624  int total_channel_count =
626 
627  // reset channels
628  memset(header->channel, 0, total_channel_count * sizeof(rl_file_channel_t));
629 
630  // write channels
631  int ch = 0;
632  for (int i = 0; i < SENSOR_REGISTRY_SIZE; i++) {
633  if (rl_status.sensor_available[i]) {
634  header->channel[ch].unit = SENSOR_REGISTRY[i].unit;
635  header->channel[ch].channel_scale = SENSOR_REGISTRY[i].scale;
637  header->channel[ch].data_size = 4;
638  strcpy(header->channel[ch].name, SENSOR_REGISTRY[i].name);
639  ch++;
640  }
641  }
642 }
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:537
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:519
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:623
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:86
@ RL_UNIT_UNDEFINED
Undefined unit.
Definition: rl_file.h:96
@ RL_UNIT_AMPERE
Current (electric)
Definition: rl_file.h:87
@ RL_UNIT_BINARY
Binary signal.
Definition: rl_file.h:88
@ RL_UNIT_RANGE_VALID
Range valid information.
Definition: rl_file.h:89
@ RL_UNIT_SECOND
Second (time delta)
Definition: rl_file.h:95
enum rl_unit rl_unit_t
Definition: rl_file.h:102
#define RL_FILE_COMMENT_ALIGNMENT_BYTES
Comment alignment in bytes.
Definition: rl_file.h:55
#define RL_SCALE_MICRO
Definition: rl_file.h:73
#define RL_SCALE_TEN_NANO
Definition: rl_file.h:72
#define RL_FILE_VERSION
File format version of current implementation.
Definition: rl_file.h:46
#define RL_SCALE_NANO
Definition: rl_file.h:71
#define RL_SCALE_MILLI
Definition: rl_file.h:74
#define RL_SCALE_TEN_PICO
Definition: rl_file.h:70
#define RL_SCALE_UNIT
Definition: rl_file.h:75
#define RL_FILE_AMBIENT_DATA_BLOCK_SIZE
Ambient sensor data file block size in measurements.
Definition: rl_file.h:64
struct rl_file_lead_in rl_file_lead_in_t
Definition: rl_file.h:137
#define RL_FILE_CHANNEL_NAME_LENGTH
Maximum channel description length.
Definition: rl_file.h:49
#define RL_FILE_AMBIENT_SUFFIX
Ambient sensor data file name suffix.
Definition: rl_file.h:61
#define RL_FILE_MAGIC
File header magic number (ascii RLD)
Definition: rl_file.h:43
#define RL_FILE_CHANNEL_NO_LINK
No additional range valid information available.
Definition: rl_file.h:52
#define RL_FILE_CSV_DELIMITER
CSV value delimiter character.
Definition: rl_file.h:58
struct rl_file_channel rl_file_channel_t
Definition: rl_file.h:158
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:152
uint16_t data_size
Datum size in bytes (for voltage and current)
Definition: rl_file.h:148
rl_unit_t unit
Channel unit.
Definition: rl_file.h:144
int32_t channel_scale
Channel scale (in power of ten, for voltage and current)
Definition: rl_file.h:146
uint16_t valid_data_channel
Link to channel valid data (for low-range current channels)
Definition: rl_file.h:150
rl_file_channel_t * channel
Channels definitions (binary and normal)
Definition: rl_file.h:169
rl_file_lead_in_t lead_in
File header lead in (constant size)
Definition: rl_file.h:165
char const * comment
Comment field.
Definition: rl_file.h:167
uint32_t comment_length
Comment length.
Definition: rl_file.h:127
uint16_t sample_rate
Sampling rate of the measurement.
Definition: rl_file.h:121
uint16_t file_version
File version number.
Definition: rl_file.h:111
rl_timestamp_t start_time
Start time of the measurement in UNIX time, UTC.
Definition: rl_file.h:125
uint64_t sample_count
Total sample count.
Definition: rl_file.h:119
uint8_t mac_address[MAC_ADDRESS_LENGTH]
Instrument ID (mac address)
Definition: rl_file.h:123
uint16_t channel_count
Analog channel count.
Definition: rl_file.h:131
uint32_t data_block_count
Number of data blocks stored in the file.
Definition: rl_file.h:117
uint32_t data_block_size
Size of the data blocks in the file in rows.
Definition: rl_file.h:115
uint16_t header_length
Total size of the header in bytes.
Definition: rl_file.h:113
uint32_t file_magic
File magic constant.
Definition: rl_file.h:109
uint16_t channel_bin_count
Binary channel count.
Definition: rl_file.h:129
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