RocketLogger 2.1.0
pru.c
Go to the documentation of this file.
1
32#include <errno.h>
33#include <stdbool.h>
34#include <stdint.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38
39#include <linux/limits.h>
40#include <pruss_intc_mapping.h>
41#include <prussdrv.h>
42#include <sys/types.h>
43#include <unistd.h>
44
45#include "calibration.h"
46#include "log.h"
47#include "meter.h"
48#include "rl.h"
49#include "rl_file.h"
50#include "rl_socket.h"
51#include "sem.h"
52#include "sensor/sensor.h"
53#include "util.h"
54
55#include "pru.h"
56
57int pru_init(void) {
58 tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
59
60 // initialize and open PRU device
61 prussdrv_init();
62 int ret = prussdrv_open(PRU_EVTOUT_0);
63 if (ret != 0) {
64 rl_log(RL_LOG_ERROR, "failed to open PRUSS driver");
65 return ERROR;
66 }
67
68 // setup PRU interrupt mapping
69 prussdrv_pruintc_init(&pruss_intc_initdata);
70
71 return SUCCESS;
72}
73
74void pru_deinit(void) {
75 // disable PRU and close memory mappings
76 prussdrv_pru_disable(0);
77 prussdrv_exit();
78}
79
81 rl_config_t const *const config, uint32_t aggregates) {
82 // zero aggregates value is also considered no aggregation
83 if (aggregates == 0) {
84 aggregates = 1;
85 }
86
87 // set state
88 if (config->sample_limit > 0) {
90 } else {
92 }
93
94 // set native sample rate in kSPS
95 if (config->sample_rate <= RL_SAMPLE_RATE_MIN) {
97 } else {
98 pru_control->sample_rate = config->sample_rate / 1000;
99 }
100
101 // set sample limit and data buffer size
102 pru_control->sample_limit = config->sample_limit * aggregates;
104 1000 * pru_control->sample_rate / config->update_rate;
105
106 // get shared buffer addresses
107 uint32_t buffer_size_bytes =
111
112 void *pru_extmem_base;
113 prussdrv_map_extmem(&pru_extmem_base);
114 uint32_t pru_extmem_phys =
115 (uint32_t)prussdrv_get_phys_addr(pru_extmem_base);
116 pru_control->buffer0_addr = pru_extmem_phys;
117 pru_control->buffer1_addr = pru_extmem_phys + buffer_size_bytes;
118
119 return SUCCESS;
120}
121
123 int res = prussdrv_pru_write_memory(PRUSS0_PRU0_DATARAM, 0,
124 (unsigned int *)&state, sizeof(state));
125 // PRU memory write fence
126 __sync_synchronize();
127 return res;
128}
129
130int pru_sample(FILE *data_file, FILE *ambient_file,
131 rl_config_t const *const config) {
132 int res;
133
134 // average (for low rates)
135 uint32_t aggregates = 1;
136 if (config->sample_rate < RL_SAMPLE_RATE_MIN) {
137 aggregates = (uint32_t)(RL_SAMPLE_RATE_MIN / config->sample_rate);
138 }
139
140 // PRU SETUP
141
142 // initialize PRU data structure
143 pru_control_t pru;
144 res = pru_control_init(&pru, config, aggregates);
145 if (res != SUCCESS) {
146 rl_log(RL_LOG_ERROR, "failed initializing PRU data structure");
147 return ERROR;
148 }
149
150 // check max PRU buffer size
151 uint32_t pru_extmem_size = (uint32_t)prussdrv_extmem_size();
152 uint32_t pru_extmem_size_demand =
153 2 * (pru.buffer_length *
156 if (pru_extmem_size_demand > pru_extmem_size) {
158 "insufficient PRU memory allocated/available.\n"
159 "update uio_pruss configuration:"
160 "options uio_pruss extram_pool_sz=0x%06x",
161 pru_extmem_size_demand);
162 pru.state = PRU_STATE_OFF;
163 }
164
165 // get user space mapped PRU memory addresses
166 void const *buffer0 = prussdrv_get_virt_addr(pru.buffer0_addr);
167 void const *buffer1 = prussdrv_get_virt_addr(pru.buffer1_addr);
168
169 // data file headers
170 rl_file_header_t data_file_header;
171 rl_file_header_t ambient_file_header;
172
173 // DATA FILE STORING
174 if (config->file_enable) {
175
176 // data file header lead-in
177 rl_file_setup_data_lead_in(&(data_file_header.lead_in), config);
178
179 // allocate channel info array
180 int total_channel_count = data_file_header.lead_in.channel_bin_count +
181 data_file_header.lead_in.channel_count;
182 data_file_header.channel = malloc(total_channel_count * sizeof(rl_file_channel_t));
183
184 // complete file header
185 rl_file_setup_data_header(&data_file_header, config);
186
187 // store header
188 if (config->file_format == RL_FILE_FORMAT_RLD) {
189 rl_file_store_header_bin(data_file, &data_file_header);
190 } else if (config->file_format == RL_FILE_FORMAT_CSV) {
191 rl_file_store_header_csv(data_file, &data_file_header);
192 }
193
194 // AMBIENT FILE STORING
195
196 // file header lead-in
197 if (config->ambient_enable) {
198
199 rl_file_setup_ambient_lead_in(&(ambient_file_header.lead_in),
200 config);
201
202 // allocate channel array
203 ambient_file_header.channel =
204 malloc(rl_status.sensor_count * sizeof(rl_file_channel_t));
205
206 // complete file header
207 rl_file_setup_ambient_header(&ambient_file_header, config);
208
209 // store header
210 rl_file_store_header_bin(ambient_file, &ambient_file_header);
211 }
212 }
213 // EXECUTION
214
215 // write configuration to PRU memory
216 prussdrv_pru_write_memory(PRUSS0_PRU0_DATARAM, 0, (unsigned int *)&pru,
217 sizeof(pru));
218
219 // PRU memory write fence
220 __sync_synchronize();
221
222 // run SPI on PRU0
223 res = prussdrv_exec_program(0, PRU_BINARY_FILE);
224 if (res < 0) {
225 rl_log(RL_LOG_ERROR, "Failed starting PRU, binary not found");
226 return ERROR;
227 }
228
229 // wait for PRU event (returns 0 on timeout, -1 on error with errno)
230 res = prussdrv_pru_wait_event_timeout(PRU_EVTOUT_0, PRU_TIMEOUT_US);
231 if (res < 0) {
232 // error checking interrupt occurred
233 rl_log(RL_LOG_ERROR, "Failed waiting for PRU interrupt; %d message: %s",
234 errno, strerror(errno));
235 return ERROR;
236 } else if (res == 0) {
237 // low level ADC timeout occurred
238 rl_log(RL_LOG_ERROR, "Failed starting PRU, PRU not responding");
239 return ERROR;
240 }
241
242 // initialize interactive measurement display when enabled
243 if (config->interactive_enable) {
244 meter_init();
245 }
246
247 // create daemon after if requested to run in background
248 if (config->background_enable) {
249 if (daemon(1, 1) < 0) {
251 "failed to create background process; %d message: %s", errno,
252 strerror(errno));
253 return ERROR;
254 }
255 }
256
257 // write PID in file (only after potential forking using daemon)
258 pid_t pid = getpid();
259 rl_pid_set(pid);
260
261 // clear event
262 prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
263
264 // CHANNEL DATA MEMORY ALLOCATION
265 int32_t *const analog_buffer = (int32_t *)malloc(
266 pru.buffer_length * RL_CHANNEL_COUNT * sizeof(int32_t));
267 uint32_t *const digital_buffer =
268 (uint32_t *)malloc(pru.buffer_length * sizeof(uint32_t));
269 int32_t sensor_buffer[SENSOR_REGISTRY_SIZE];
270
271 pru_buffer_t const *pru_buffer = NULL;
272 size_t buffer_size; // number of data samples per buffer
273 size_t sensor_buffer_size = 0;
274 uint32_t sensor_rate_counter = 0;
275 rl_timestamp_t timestamp_monotonic;
276 rl_timestamp_t timestamp_realtime;
277 uint32_t buffers_lost = 0;
278 uint32_t num_files = 1; // number of files stored
279 bool web_failure_disable = false;
280
281 // buffers to read in finite mode
282 uint32_t buffer_read_count =
283 div_ceil(config->sample_limit * aggregates, pru.buffer_length);
284
285 // sampling started
286 rl_status.sampling = true;
288 if (res < 0) {
289 rl_log(RL_LOG_WARNING, "Failed writing status; %d message: %s", errno,
290 strerror(errno));
291 }
292
293 // continuous sampling loop
294 for (uint32_t i = 0; rl_status.sampling &&
295 !(config->sample_limit > 0 && i >= buffer_read_count);
296 i++) {
297
298 if (config->file_enable) {
299
300 // check if max file size reached
301 uint64_t file_size = (uint64_t)ftello(data_file);
302 if (config->file_size > 0 &&
303 file_size + rl_status.disk_use_rate > config->file_size) {
304
305 // close old data file
306 fclose(data_file);
307
308 // determine new file name
309 char file_name[PATH_MAX];
310 char new_file_ending[PATH_MAX];
311 strcpy(file_name, config->file_name);
312
313 // search for last .
314 char target = '.';
315 char *file_ending = file_name;
316 while (strchr(file_ending, target) != NULL) {
317 file_ending = strchr(file_ending, target);
318 file_ending++; // Increment file_ending, otherwise we'll
319 // find target at the same location
320 }
321 file_ending--;
322
323 // add file number
324 sprintf(new_file_ending, "_p%d", num_files);
325 strcat(new_file_ending, file_ending);
326 strcpy(file_ending, new_file_ending);
327
328 // open new data file
329 data_file = fopen64(file_name, "w+");
330
331 // update header for new file
332 data_file_header.lead_in.data_block_count = 0;
333 data_file_header.lead_in.sample_count = 0;
334
335 // store header
336 if (config->file_format == RL_FILE_FORMAT_RLD) {
337 rl_file_store_header_bin(data_file, &data_file_header);
338 } else if (config->file_format == RL_FILE_FORMAT_CSV) {
339 rl_file_store_header_csv(data_file, &data_file_header);
340 }
341
342 rl_log(RL_LOG_INFO, "Creating new data file: %s", file_name);
343
344 // AMBIENT FILE
345 if (config->ambient_enable) {
346 // close old ambient file
347 fclose(ambient_file);
348
349 // determine new file name
350 char *ambient_file_name =
352 strcpy(file_name, ambient_file_name);
353
354 // search for last .
355 file_ending = file_name;
356 while (strchr(file_ending, target) != NULL) {
357 file_ending = strchr(file_ending, target);
358 file_ending++; // Increment file_ending, otherwise we'll
359 // find target at the same location
360 }
361 file_ending--;
362
363 // add file number
364 sprintf(new_file_ending, "_p%d", num_files);
365 strcat(new_file_ending, file_ending);
366 strcpy(file_ending, new_file_ending);
367
368 // open new ambient file
369 ambient_file = fopen64(file_name, "w+");
370
371 // update header for new file
372 ambient_file_header.lead_in.data_block_count = 0;
373 ambient_file_header.lead_in.sample_count = 0;
374
375 // store header
376 rl_file_store_header_bin(ambient_file,
377 &ambient_file_header);
378
379 rl_log(RL_LOG_INFO, "new ambient-file: %s", file_name);
380 }
381
382 num_files++;
383 }
384 }
385
386 // select current buffer
387 if (i % 2 == 0) {
388 pru_buffer = buffer0;
389 } else {
390 pru_buffer = buffer1;
391 }
392
393 // select buffer size, repecting non-full last buffer
394 if (i < buffer_read_count - 1 ||
395 pru.sample_limit % pru.buffer_length == 0) {
396 buffer_size = (size_t)pru.buffer_length;
397 } else {
398 // last buffer is not fully used
399 buffer_size = (size_t)(pru.sample_limit % pru.buffer_length);
400 }
401
402 // trigger new ambient sensor read out if enabled
403 sensor_buffer_size = 0;
404 if (config->ambient_enable) {
405 // rate limit sampling of the ambient sensors
406 if (sensor_rate_counter < RL_SENSOR_SAMPLE_RATE) {
407 // trigger sensor readout
408 sensor_buffer_size =
410 }
411 // increment rate limiting counter
412 sensor_rate_counter =
413 (sensor_rate_counter + RL_SENSOR_SAMPLE_RATE) %
414 config->update_rate;
415 }
416
417 // wait for PRU event indicating new data (repeat wait on interrupts)
418 do {
419 // wait for PRU event (returns 0 on timeout, -1 on error with errno)
420 res = prussdrv_pru_wait_event_timeout(PRU_EVTOUT_0, PRU_TIMEOUT_US);
421 // timestamp received data
422 create_time_stamp(&timestamp_realtime, &timestamp_monotonic);
423 } while (res < 0 && errno == EINTR);
424 if (res < 0) {
425 // error checking interrupt occurred
427 "Failed waiting for PRU interrupt; %d message: %s", errno,
428 strerror(errno));
429 rl_status.error = true;
430 break;
431 } else if (res == 0) {
432 // low level ADC timeout occurred
433 rl_log(RL_LOG_ERROR, "ADC not responsive");
434 rl_status.error = true;
435 break;
436 }
437
438 // adjust data timestamps with buffer latency (adjusted relative
439 // nanoseconds)
440 timestamp_realtime.nsec -= (int64_t)2048e3 * 490 / config->update_rate;
441 if (timestamp_realtime.nsec < 0) {
442 timestamp_realtime.sec -= 1;
443 timestamp_realtime.nsec += (int64_t)1e9;
444 }
445 timestamp_monotonic.nsec -= (int64_t)2048e3 * 490 / config->update_rate;
446 if (timestamp_monotonic.nsec < 0) {
447 timestamp_monotonic.sec -= 1;
448 timestamp_monotonic.nsec += (int64_t)1e9;
449 }
450
451 // clear event
452 prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
453
454 // PRU memory sync before accessing data
455 __sync_synchronize();
456
457 // check for overrun (compare buffer numbers)
458 if (pru_buffer->index != i) {
459 buffers_lost += (pru_buffer->index - i);
461 "overrun: %d samples (%d buffer) lost (%d in total)",
462 (pru_buffer->index - i) * pru.buffer_length,
463 pru_buffer->index - i, buffers_lost);
464 i = pru_buffer->index;
465 }
466
467 // process new data: copy data and apply calibration
468 for (size_t i = 0; i < buffer_size; i++) {
469 // get PRU data buffer pointer
470 pru_data_t const *const pru_data = &(pru_buffer->data[i]);
471
472 // get local data buffer pointers
473 int32_t *const analog_data = analog_buffer + i * RL_CHANNEL_COUNT;
474 uint32_t *const digital_data = digital_buffer + i;
475
476 // copy digital channel data
477 *digital_data = pru_data->channel_digital;
478
479 // copy and calibrate analog channel data
480 for (int j = 0; j < RL_CHANNEL_COUNT; j++) {
481 analog_data[j] = (int32_t)((pru_data->channel_analog[j] +
484 }
485 }
486
487 // update and write state
488 rl_status.sample_count += buffer_size / aggregates;
489 rl_status.buffer_count = i + 1 - buffers_lost;
491 if (res < 0) {
492 rl_log(RL_LOG_WARNING, "Failed writing status; %d message: %s",
493 errno, strerror(errno));
494 }
495
496 // process data for web when enabled
497 if (config->web_enable && !web_failure_disable) {
498 res = rl_socket_handle_data(analog_buffer, digital_buffer,
499 sensor_buffer, buffer_size,
500 sensor_buffer_size, &timestamp_realtime,
501 &timestamp_monotonic, config);
502 if (res < 0) {
503 // disable web interface on failure, but continue sampling
504 web_failure_disable = true;
506 "Web server connection failed; %d message: %s", errno,
507 strerror(errno));
509 "Disabling web interface and continue sampling.");
510 }
511 }
512
513 // update and write header
514 if (config->file_enable) {
515 // write the data buffer to file
516 int block_count = rl_file_add_data_block(
517 data_file, analog_buffer, digital_buffer, buffer_size,
518 &timestamp_realtime, &timestamp_monotonic, config);
519
520 // stop sampling on file error
521 if (block_count < 0) {
523 "Adding data block to data file failed; %d message: %s",
524 errno, strerror(errno));
525 rl_status.error = true;
526 break;
527 }
528
529 // update and store data file header
530 data_file_header.lead_in.data_block_count += block_count;
531 data_file_header.lead_in.sample_count +=
532 block_count * (buffer_size / aggregates);
533
534 if (config->file_format == RL_FILE_FORMAT_RLD) {
535 rl_file_update_header_bin(data_file, &data_file_header);
536 } else if (config->file_format == RL_FILE_FORMAT_CSV) {
537 rl_file_update_header_csv(data_file, &data_file_header);
538 }
539 }
540
541 // handle ambient data if enabled and available
542 if (config->ambient_enable && sensor_buffer_size > 0) {
543 // fetch and write data
544 int block_count = rl_file_add_ambient_block(
545 ambient_file, sensor_buffer, sensor_buffer_size,
546 &timestamp_realtime, &timestamp_monotonic, config);
547
548 // stop sampling on file error
549 if (block_count < 0) {
550 rl_log(
552 "Adding data block to ambient file failed; %d message: %s",
553 errno, strerror(errno));
554 rl_status.error = true;
555 break;
556 }
557
558 // update and write header
559 ambient_file_header.lead_in.data_block_count += block_count;
560 ambient_file_header.lead_in.sample_count +=
562 rl_file_update_header_bin(ambient_file, &ambient_file_header);
563 }
564
565 // print meter output if enabled
566 if (config->interactive_enable) {
567 meter_print_buffer(analog_buffer, digital_buffer, buffer_size,
568 &timestamp_realtime, &timestamp_monotonic,
569 config);
570 }
571 }
572
573 // stop PRU
574 pru_stop();
575
576 // sampling stopped, update status
577 rl_status.sampling = false;
579 if (res < 0) {
580 rl_log(RL_LOG_WARNING, "Failed writing status; %d message: %s", errno,
581 strerror(errno));
582 }
583
584 // CLEANUP CHANNEL DATA MEMORY ALLOCATION
585 free(analog_buffer);
586 free(digital_buffer);
587
588 // deinitialize interactive measurement display when enabled
589 if (config->interactive_enable) {
590 meter_deinit();
591 }
592
593 // FILE FINISH (flush)
594 if (config->file_enable) {
595 // flush data file and clean up file header
596 fflush(data_file);
597 free(data_file_header.channel);
598
599 // flush ambient file and clean up file header
600 if (config->ambient_enable) {
601 fflush(ambient_file);
602 free(ambient_file_header.channel);
603 }
604
605 if (rl_status.error == false) {
606 rl_log(RL_LOG_INFO, "stored %llu samples to file",
608 }
609 }
610
611 // STATE
612 if (rl_status.error) {
613 return ERROR;
614 }
615
616 return SUCCESS;
617}
618
619void pru_stop(void) {
620
621 // write OFF to PRU state (so PRU can clean up)
623
624 // wait for interrupt (if no ERROR occurred) and clear event
625 if (!(rl_status.error)) {
626 // wait for PRU event (returns 0 on timeout, -1 on error with errno)
627 prussdrv_pru_wait_event_timeout(PRU_EVTOUT_0, PRU_TIMEOUT_US);
628 prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
629 }
630}
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
@ RL_LOG_INFO
Information.
Definition: log.h:51
void meter_init(void)
Definition: meter.c:56
void meter_print_buffer(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: meter.c:68
void meter_deinit(void)
Definition: meter.c:66
int pru_sample(FILE *data_file, FILE *ambient_file, rl_config_t const *const config)
Definition: pru.c:130
void pru_deinit(void)
Definition: pru.c:74
int pru_control_init(pru_control_t *const pru_control, rl_config_t const *const config, uint32_t aggregates)
Definition: pru.c:80
void pru_stop(void)
Definition: pru.c:619
int pru_init(void)
Definition: pru.c:57
int pru_set_state(pru_state_t state)
Definition: pru.c:122
@ PRU_STATE_OFF
Definition: pru.h:70
@ PRU_STATE_SAMPLE_FINITE
PRU off.
Definition: pru.h:71
@ PRU_STATE_SAMPLE_CONTINUOUS
PRU sampling in finite mode.
Definition: pru.h:72
#define PRU_BINARY_FILE
PRU binary file location.
Definition: pru.h:41
#define PRU_BUFFER_STATUS_SIZE
Size of PRU buffer status in bytes.
Definition: pru.h:48
#define PRU_SAMPLE_SIZE
Size of PRU channel data in bytes.
Definition: pru.h:46
#define PRU_DIGITAL_SIZE
Overall size of FRU digital channels in bytes.
Definition: pru.h:44
enum pru_state pru_state_t
Definition: pru.h:78
#define PRU_TIMEOUT_US
PRU time out in micro seconds.
Definition: pru.h:64
int rl_status_write(rl_status_t *const status)
Definition: rl.c:641
int rl_pid_set(pid_t pid)
Definition: rl.c:521
@ 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 SUCCESS
Function return value for successful completion.
Definition: rl.h:44
#define RL_CHANNEL_COUNT
Number of RocketLogger analog channels.
Definition: rl.h:56
void rl_file_store_header_bin(FILE *file_handle, rl_file_header_t *const file_header)
Definition: rl_file.c:218
void rl_file_update_header_bin(FILE *file_handle, rl_file_header_t const *const file_header)
Definition: rl_file.c:325
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
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_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:521
char * rl_file_get_ambient_file_name(char const *const data_file_name)
Definition: rl_file.c:95
void rl_file_setup_data_header(rl_file_header_t *const header, rl_config_t const *const config)
Definition: rl_file.c:196
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
#define RL_FILE_AMBIENT_DATA_BLOCK_SIZE
Ambient sensor data file block size in measurements.
Definition: rl_file.h:64
int rl_socket_handle_data(int32_t const *analog_buffer, uint32_t const *digital_buffer, int32_t const *ambient_buffer, size_t buffer_size, size_t ambient_buffer_size, rl_timestamp_t const *const timestamp_realtime, rl_timestamp_t const *const timestamp_monotonic, rl_config_t const *const config)
Definition: rl_socket.c:157
int sensors_read(int32_t *const sensor_data, bool const sensor_available[SENSOR_REGISTRY_SIZE])
Definition: sensor.c:198
#define SENSOR_REGISTRY_SIZE
Number of sensor registered.
Definition: sensor.h:47
uint32_t index
buffer index
Definition: pru.h:129
pru_data_t const data[]
the data blocks
Definition: pru.h:131
uint32_t sample_rate
Sample rate of the ADC (in kSPS)
Definition: pru.h:87
uint32_t sample_limit
Samples to take (0 for continuous)
Definition: pru.h:89
uint32_t buffer0_addr
Memory address of the shared buffer 0.
Definition: pru.h:93
uint32_t buffer1_addr
Memory address of the shared buffer 1.
Definition: pru.h:95
pru_state_t state
Current PRU state.
Definition: pru.h:85
uint32_t buffer_length
Shared buffer length in number of data elements.
Definition: pru.h:91
Definition: pru.h:106
int32_t channel_analog[RL_CHANNEL_COUNT]
Definition: pru.h:116
uint32_t channel_digital
Definition: pru.h:111
double scales[RL_CHANNEL_COUNT]
Channel scales.
Definition: calibration.h:53
int offsets[RL_CHANNEL_COUNT]
Channel offsets (in bit)
Definition: calibration.h:51
Definition: rl.h:154
char file_name[PATH_MAX]
Data file name.
Definition: rl.h:184
bool interactive_enable
Display measurement data interactively in CLI while sampling.
Definition: rl.h:160
uint64_t file_size
Maximum data file size.
Definition: rl.h:188
bool background_enable
Put the measurement process in background after successful start.
Definition: rl.h:158
bool ambient_enable
Enable logging of ambient sensor.
Definition: rl.h:180
uint64_t sample_limit
Sample limit (0 for continuous)
Definition: rl.h:162
bool web_enable
Enable web interface connection.
Definition: rl.h:176
rl_file_format_t file_format
File format.
Definition: rl.h:186
uint32_t sample_rate
Sampling rate.
Definition: rl.h:164
uint32_t update_rate
Data update rate.
Definition: rl.h:166
bool file_enable
Enable storing measurements to file.
Definition: rl.h:182
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
uint64_t sample_count
Total sample count.
Definition: rl_file.h:119
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
uint16_t channel_bin_count
Binary channel count.
Definition: rl_file.h:129
Definition: rl.h:201
uint64_t buffer_count
Number of buffers taken.
Definition: rl.h:209
bool error
Whether the logger is in an error state.
Definition: rl.h:205
bool sampling
Sampling state, true: sampling, false: idle.
Definition: rl.h:203
uint32_t disk_use_rate
Disk space in bytes required per minute when sampling.
Definition: rl.h:219
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
uint64_t sample_count
Number of samples taken.
Definition: rl.h:207
int64_t nsec
Nanoseconds.
Definition: util.h:53
int64_t sec
Seconds in UNIX time (UTC)
Definition: util.h:51
int div_ceil(int n, int d)
Definition: util.c:82
void create_time_stamp(rl_timestamp_t *const timestamp_realtime, rl_timestamp_t *const timestamp_monotonic)
Definition: util.c:90