38 #include <linux/limits.h>
87 if ((
unsigned int)unit <
96 static char ambient_file_name[PATH_MAX];
99 strcpy(ambient_file_name, data_file_name);
103 char *file_ending = ambient_file_name;
104 while (strchr(file_ending, target) != NULL) {
105 file_ending = strchr(file_ending, target);
113 strcat(ambient_file_ending, file_ending);
114 strcpy(file_ending, ambient_file_ending);
116 return ambient_file_name;
125 uint16_t channel_bin_count = 0;
167 uint16_t channel_bin_count = 0;
225 int comment_length = strlen(file_header->
comment) + 1;
226 int comment_align_bytes = 0;
228 comment_align_bytes =
243 fwrite(file_header->
comment, comment_length, 1, file_handle);
244 if (comment_align_bytes > 0) {
246 fwrite(zero_bytes, comment_align_bytes, 1, file_handle);
258 fprintf(file_handle,
"RocketLogger CSV File\n");
259 fprintf(file_handle,
"File Version,%u\n",
261 fprintf(file_handle,
"Block Size,%u\n",
263 fprintf(file_handle,
"Block Count,%-20u\n",
265 fprintf(file_handle,
"Sample Count,%-20llu\n",
267 fprintf(file_handle,
"Sample Rate,%u\n",
269 fprintf(file_handle,
"MAC Address,%02x",
273 fprintf(file_handle,
":%02x",
276 fprintf(file_handle,
"\n");
279 fprintf(file_handle,
"Start Time,%s", ctime(&time));
280 fprintf(file_handle,
"Comment,%s\n", file_header->
comment);
281 fprintf(file_handle,
"\n");
287 fprintf(file_handle,
",%s", file_header->
channel[i].
name);
290 fprintf(file_handle,
" [m");
293 fprintf(file_handle,
" [u");
296 fprintf(file_handle,
" [10n");
299 fprintf(file_handle,
" [n");
302 fprintf(file_handle,
" [10p");
309 fprintf(file_handle,
"V]");
312 fprintf(file_handle,
"A]");
315 fprintf(file_handle,
"s]");
321 fprintf(file_handle,
"\n");
332 fseek(file_handle, 0, SEEK_END);
338 fprintf(file_handle,
"RocketLogger CSV File\n");
339 fprintf(file_handle,
"File Version,%u\n",
341 fprintf(file_handle,
"Block Size,%u\n",
343 fprintf(file_handle,
"Block Count,%-20u\n",
345 fprintf(file_handle,
"Sample Count,%-20llu\n",
348 fseek(file_handle, 0, SEEK_END);
352 uint32_t
const *digital_buffer,
size_t buffer_size,
359 uint32_t aggregate_digital = ~((uint32_t)0);
366 if (data_file == NULL) {
371 if (aggregate_count > buffer_size) {
381 fwrite(timestamp_monotonic,
sizeof(
rl_timestamp_t), 1, data_file);
383 fprintf(data_file,
"%lli.%09lli", timestamp_realtime->
sec,
384 timestamp_realtime->
nsec);
388 for (
size_t i = 0; i < buffer_size; i++) {
391 uint32_t
const *digital_data = digital_buffer + i;
394 if (aggregate_count > 1) {
395 bool aggregate_store =
false;
398 if (i % aggregate_count == 0) {
399 memset(aggregate_analog_sum, 0,
sizeof(aggregate_analog_sum));
400 aggregate_digital = ~(0);
406 if (i % aggregate_count == 0) {
408 aggregate_store =
true;
415 aggregate_analog_sum[j] += *(analog_data + j);
417 aggregate_digital = aggregate_digital & *digital_data;
420 if ((i + 1) % aggregate_count == 0) {
423 aggregate_analog[j] =
424 aggregate_analog_sum[j] / aggregate_count;
428 analog_data = aggregate_analog;
429 digital_data = &aggregate_digital;
430 aggregate_store =
true;
436 "unknown data aggregation mode, storing all samples.");
437 aggregate_store =
true;
441 if (!aggregate_store) {
449 uint32_t
data = 0x00;
458 data |= (1 << index);
464 data |= (1 << index);
471 fwrite(&
data,
sizeof(
data), 1, data_file);
478 (*digital_data & binary_mask) > 0);
479 binary_mask = binary_mask << 1;
500 fwrite(&analog_data[j],
sizeof(int32_t), 1, data_file);
509 fprintf(data_file,
"\n");
530 fwrite(timestamp_realtime,
sizeof(
rl_timestamp_t), 1, ambient_file);
531 fwrite(timestamp_monotonic,
sizeof(
rl_timestamp_t), 1, ambient_file);
534 fwrite(ambient_buffer,
sizeof(int32_t), buffer_size, ambient_file);
545 memset(file_header->
channel, 0,
626 int total_channel_count =
rl_calibration_t data
The actual calibration data.
int rl_log(rl_log_level_t log_level, char const *const format,...)
#define PRU_DIGITAL_INPUT1_MASK
#define PRU_DIGITAL_I1L_VALID_MASK
#define PRU_DIGITAL_I2L_VALID_MASK
#define PRU_DIGITAL_INPUT_MASK
char const *const RL_CHANNEL_NAMES[RL_CHANNEL_COUNT]
RocketLogger channel names.
char const *const RL_CHANNEL_VALID_NAMES[RL_CHANNEL_SWITCHED_COUNT]
RocketLogger valid channel names.
char const *const RL_CHANNEL_DIGITAL_NAMES[RL_CHANNEL_DIGITAL_COUNT]
RocketLogger digital channel names.
#define RL_CONFIG_CHANNEL_I2L
@ RL_FILE_FORMAT_RLD
CSV format.
#define RL_SENSOR_SAMPLE_RATE
Ambient sensor read out rate in samples per second.
#define RL_SAMPLE_RATE_MIN
Minimum native sample rate of the ADC in samples per second.
#define ERROR
Function return value for errors (use errno to indicate the error)
#define RL_CHANNEL_DIGITAL_COUNT
Number of RocketLogger digital channels.
#define RL_CONFIG_CHANNEL_I1L
#define RL_CHANNEL_COUNT
Number of RocketLogger analog channels.
@ RL_AGGREGATION_MODE_AVERAGE
Aggregate using down sampling.
@ RL_AGGREGATION_MODE_DOWNSAMPLE
char * rl_unit_to_string(rl_unit_t const unit)
void rl_file_store_header_bin(FILE *file_handle, rl_file_header_t *const file_header)
int i1l_valid_channel
Global variable to determine i1l valid channel index.
void rl_file_update_header_bin(FILE *file_handle, rl_file_header_t const *const file_header)
int i2l_valid_channel
Global variable to determine i2l valid channel index.
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)
void rl_file_store_header_csv(FILE *file_handle, rl_file_header_t const *const file_header)
void rl_file_setup_data_channels(rl_file_header_t *const header, rl_config_t const *const config)
void rl_file_setup_ambient_lead_in(rl_file_lead_in_t *const lead_in, rl_config_t const *const config)
void rl_file_setup_ambient_header(rl_file_header_t *const header, rl_config_t const *const config)
void rl_file_update_header_csv(FILE *file_handle, rl_file_header_t const *const file_header)
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)
void rl_file_setup_data_header(rl_file_header_t *const header, rl_config_t const *const config)
char * rl_file_get_ambient_file_name(char const *const data_file_name)
void rl_file_setup_ambient_channels(rl_file_header_t *const header)
void rl_file_setup_data_lead_in(rl_file_lead_in_t *const lead_in, rl_config_t const *const config)
@ RL_UNIT_VOLT
Voltage (electric)
@ RL_UNIT_UNDEFINED
Undefined unit.
@ RL_UNIT_AMPERE
Current (electric)
@ RL_UNIT_BINARY
Binary signal.
@ RL_UNIT_RANGE_VALID
Range valid information.
@ RL_UNIT_SECOND
Second (time delta)
#define RL_FILE_COMMENT_ALIGNMENT_BYTES
Comment alignment in bytes.
#define RL_SCALE_TEN_NANO
#define RL_FILE_VERSION
File format version of current implementation.
#define RL_SCALE_TEN_PICO
#define RL_FILE_AMBIENT_DATA_BLOCK_SIZE
Ambient sensor data file block size in measurements.
struct rl_file_lead_in rl_file_lead_in_t
#define RL_FILE_CHANNEL_NAME_LENGTH
Maximum channel description length.
#define RL_FILE_AMBIENT_SUFFIX
Ambient sensor data file name suffix.
#define RL_FILE_MAGIC
File header magic number (ascii RLD)
#define RL_FILE_CHANNEL_NO_LINK
No additional range valid information available.
#define RL_FILE_CSV_DELIMITER
CSV value delimiter character.
struct rl_file_channel rl_file_channel_t
const rl_sensor_t SENSOR_REGISTRY[SENSOR_REGISTRY_SIZE]
#define SENSOR_REGISTRY_SIZE
Number of sensor registered.
char const * file_comment
File comment.
rl_aggregation_mode_t aggregation_mode
Sample aggregation mode (for sampling rates below lowest native one)
rl_file_format_t file_format
File format.
uint32_t sample_rate
Sampling rate.
bool channel_enable[RL_CHANNEL_COUNT]
Channels to sample.
uint32_t update_rate
Data update rate.
bool file_enable
Enable storing measurements to file.
bool digital_enable
Enable digital inputs.
bool calibration_ignore
Perform calibration measurement (ignore existing calibration)
char name[RL_FILE_CHANNEL_NAME_LENGTH]
Channel name/description.
uint16_t data_size
Datum size in bytes (for voltage and current)
rl_unit_t unit
Channel unit.
int32_t channel_scale
Channel scale (in power of ten, for voltage and current)
uint16_t valid_data_channel
Link to channel valid data (for low-range current channels)
uint32_t comment_length
Comment length.
uint16_t sample_rate
Sampling rate of the measurement.
uint16_t file_version
File version number.
rl_timestamp_t start_time
Start time of the measurement in UNIX time, UTC.
uint64_t sample_count
Total sample count.
uint8_t mac_address[MAC_ADDRESS_LENGTH]
Instrument ID (mac address)
uint16_t channel_count
Analog channel count.
uint32_t data_block_count
Number of data blocks stored in the file.
uint32_t data_block_size
Size of the data blocks in the file in rows.
uint16_t header_length
Total size of the header in bytes.
uint32_t file_magic
File magic constant.
uint16_t channel_bin_count
Binary channel count.
char name[SENSOR_NAME_LENGTH]
uint16_t sensor_count
Number of sensors found connected to the system.
bool sensor_available[RL_SENSOR_COUNT_MAX]
Identifiers of sensors found.
int64_t sec
Seconds in UNIX time (UTC)
bool is_current(int index)
int count_channels(bool const channels[RL_CHANNEL_COUNT])
void create_time_stamp(rl_timestamp_t *const timestamp_realtime, rl_timestamp_t *const timestamp_monotonic)
void get_mac_addr(uint8_t mac_address[MAC_ADDRESS_LENGTH])
bool is_low_current(int index)
bool is_voltage(int index)
#define MAC_ADDRESS_LENGTH
MAC address length in bytes.