RocketLogger  1.1.5
pru.c
Go to the documentation of this file.
1 
32 #include <stdint.h>
33 
34 #include <sys/ipc.h>
35 #include <sys/sem.h>
36 #include <sys/types.h>
37 
38 #include "file_handling.h"
39 #include "util.h"
40 #include "web.h"
41 
42 #include "pru.h"
43 
44 // PRU TIMEOUT WRAPPER
45 
47 pthread_mutex_t waiting = PTHREAD_MUTEX_INITIALIZER;
48 
50 pthread_cond_t done = PTHREAD_COND_INITIALIZER;
51 
56 void* pru_wait_event(void* voidEvent) {
57 
58  unsigned int event = *((unsigned int*)voidEvent);
59 
60  // allow the thread to be killed at any time
61  int oldtype;
62  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
63 
64  // wait for pru event
65  prussdrv_pru_wait_event(event);
66 
67  // notify main program
68  pthread_cond_signal(&done);
69 
70  return NULL;
71 }
72 
79 int pru_wait_event_timeout(unsigned int event, unsigned int timeout) {
80 
81  struct timespec abs_time;
82  pthread_t tid;
83  int err;
84 
85  pthread_mutex_lock(&waiting);
86 
87  // pthread cond_timedwait expects an absolute time to wait until
88  clock_gettime(CLOCK_REALTIME, &abs_time);
89  abs_time.tv_sec += timeout;
90 
91  pthread_create(&tid, NULL, pru_wait_event, (void*)&event);
92 
93  err = pthread_cond_timedwait(&done, &waiting, &abs_time);
94 
95  if (!err) {
96  pthread_mutex_unlock(&waiting);
97  }
98 
99  return err;
100 }
101 
102 // PRU MEMORY MAPPING
106 void* pru_map_memory(void) {
107 
108  // get pru memory location and size
109  unsigned int pru_memory = read_file_value(MMAP_FILE "addr");
110  unsigned int size = read_file_value(MMAP_FILE "size");
111 
112  // memory map file
113  int fd;
114  if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
115  rl_log(ERROR, "failed to open /dev/mem");
116  return NULL;
117  }
118 
119  // map shared memory into userspace
120  void* pru_mmap = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
121  (off_t)pru_memory);
122 
123  if (pru_mmap == (void*)-1) {
124  rl_log(ERROR, "failed to map base address");
125  return NULL;
126  }
127 
128  close(fd);
129 
130  return pru_mmap;
131 }
132 
138 int pru_unmap_memory(void* pru_mmap) {
139 
140  // get pru memory size
141  unsigned int size = read_file_value(MMAP_FILE "size");
142 
143  if (munmap(pru_mmap, size) == -1) {
144  rl_log(ERROR, "failed to unmap memory");
145  return FAILURE;
146  }
147 
148  return SUCCESS;
149 }
150 
151 // PRU INITIALISATION
152 
158 
159  prussdrv_pru_write_memory(PRUSS0_PRU0_DATARAM, 0, (unsigned int*)&state,
160  sizeof(int));
161 }
162 
167 int pru_init(void) {
168 
169  // init PRU
170  tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
171  prussdrv_init();
172  if (prussdrv_open(PRU_EVTOUT_0) == -1) {
173  rl_log(ERROR, "failed to open PRU");
174  return FAILURE;
175  }
176  prussdrv_pruintc_init(&pruss_intc_initdata);
177 
178  return SUCCESS;
179 }
180 
189 int pru_data_setup(struct pru_data_struct* pru, struct rl_conf* conf,
190  uint32_t avg_factor) {
191 
192  uint32_t pru_sample_rate;
193 
194  // set state
195  if (conf->mode == LIMIT) {
196  pru->state = PRU_LIMIT;
197  } else {
198  pru->state = PRU_CONTINUOUS;
199  }
200 
201  // set sampling rate configuration
202  switch (conf->sample_rate) {
203  case 1:
204  pru_sample_rate = K1;
205  pru->precision = PRECISION_HIGH;
206  pru->sample_size = SIZE_HIGH;
207  break;
208  case 10:
209  pru_sample_rate = K1;
210  pru->precision = PRECISION_HIGH;
211  pru->sample_size = SIZE_HIGH;
212  break;
213  case 100:
214  pru_sample_rate = K1;
215  pru->precision = PRECISION_HIGH;
216  pru->sample_size = SIZE_HIGH;
217  break;
218  case 1000:
219  pru_sample_rate = K1;
220  pru->precision = PRECISION_HIGH;
221  pru->sample_size = SIZE_HIGH;
222  break;
223  case 2000:
224  pru_sample_rate = K2;
225  pru->precision = PRECISION_HIGH;
226  pru->sample_size = SIZE_HIGH;
227  break;
228  case 4000:
229  pru_sample_rate = K4;
230  pru->precision = PRECISION_HIGH;
231  pru->sample_size = SIZE_HIGH;
232  break;
233  case 8000:
234  pru_sample_rate = K8;
235  pru->precision = PRECISION_HIGH;
236  pru->sample_size = SIZE_HIGH;
237  break;
238  case 16000:
239  pru_sample_rate = K16;
240  pru->precision = PRECISION_HIGH;
241  pru->sample_size = SIZE_HIGH;
242  break;
243  case 32000:
244  pru_sample_rate = K32;
245  pru->precision = PRECISION_LOW;
246  pru->sample_size = SIZE_HIGH;
247  break;
248  case 64000:
249  pru_sample_rate = K64;
250  pru->precision = PRECISION_LOW;
251  pru->sample_size = SIZE_HIGH;
252  break;
253  default:
254  rl_log(ERROR, "wrong sample rate");
255  return FAILURE;
256  }
257 
258  // set buffer infos
259  pru->sample_limit = conf->sample_limit * avg_factor;
260  pru->buffer_size = (conf->sample_rate * avg_factor) / conf->update_rate;
261 
262  uint32_t buffer_size_bytes =
266  pru->buffer1_location = pru->buffer0_location + buffer_size_bytes;
267 
268  // set commands
270  pru->commands[0] = RESET;
271  pru->commands[1] = SDATAC;
272  pru->commands[2] = WREG | CONFIG3 | CONFIG3DEFAULT; // write configuration
273  pru->commands[3] = WREG | CONFIG1 | CONFIG1DEFAULT | pru_sample_rate;
274 
275  // set channel gains
276  pru->commands[4] = WREG | CH1SET | GAIN2; // High Range A
277  pru->commands[5] = WREG | CH2SET | GAIN2; // High Range B
278  pru->commands[6] = WREG | CH3SET | GAIN1; // Medium Range
279  pru->commands[7] = WREG | CH4SET | GAIN1; // Low Range A
280  pru->commands[8] = WREG | CH5SET | GAIN1; // Low Range B
281  pru->commands[9] = WREG | CH6SET | GAIN1; // Voltage 1
282  pru->commands[10] = WREG | CH7SET | GAIN1; // Voltage 2
283  pru->commands[11] = RDATAC; // continuous reading
284 
285  return SUCCESS;
286 }
287 
296 int pru_sample(FILE* data_file, FILE* ambient_file, struct rl_conf* conf,
297  char* file_comment) {
298 
299  // average (for low rates)
300  uint32_t avg_factor = 1;
301  if (conf->sample_rate < MIN_ADC_RATE) {
302  avg_factor = MIN_ADC_RATE / conf->sample_rate;
303  }
304 
305  // METER
306  if (conf->mode == METER) {
307  meter_init();
308  }
309 
310  // WEBSERVER
311  int sem_id = -1;
312  struct web_shm* web_data = (struct web_shm*)-1;
313 
314  if (conf->enable_web_server == 1) {
315  // semaphores
316  sem_id = create_sem(SEM_KEY, NUM_SEMS);
317  set_sem(sem_id, DATA_SEM, 1);
318 
319  // shared memory
320  web_data = web_create_shm();
321 
322  // determine web channels count (merged)
323  int num_web_channels = count_channels(conf->channels);
324  if (conf->channels[I1H_INDEX] == CHANNEL_ENABLED &&
325  conf->channels[I1L_INDEX] == CHANNEL_ENABLED) {
326  num_web_channels--;
327  }
328  if (conf->channels[I2H_INDEX] == CHANNEL_ENABLED &&
329  conf->channels[I2L_INDEX] == CHANNEL_ENABLED) {
330  num_web_channels--;
331  }
332  if (conf->digital_inputs == DIGITAL_INPUTS_ENABLED) {
333  num_web_channels += NUM_DIGITAL_INPUTS;
334  }
335  web_data->num_channels = num_web_channels;
336 
337  // web buffer sizes
340 
341  for (int i = 0; i < WEB_RING_BUFFER_COUNT; i++) {
342  int web_buffer_element_size =
343  buffer_sizes[i] * num_web_channels * sizeof(int64_t);
344  int web_buffer_length = NUM_WEB_POINTS / buffer_sizes[i];
345  web_buffer_reset(&web_data->buffer[i], web_buffer_element_size,
346  web_buffer_length);
347  }
348  }
349 
350  // PRU SETUP
351 
352  // Map the PRU's interrupts
353  tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
354  prussdrv_pruintc_init(&pruss_intc_initdata);
355 
356  // setup PRU
357  struct pru_data_struct pru;
358  pru_data_setup(&pru, conf, avg_factor);
359  unsigned int number_buffers =
360  ceil_div(conf->sample_limit * avg_factor, pru.buffer_size);
361  unsigned int buffer_size_bytes =
364 
365  // check memory size
366  unsigned int max_size = read_file_value(MMAP_FILE "size");
367  if (2 * buffer_size_bytes > max_size) {
368  rl_log(ERROR, "not enough memory allocated. Run:\n rmmod uio_pruss\n "
369  "modprobe uio_pruss extram_pool_sz=0x%06x",
370  2 * buffer_size_bytes);
371  pru.state = PRU_OFF;
372  }
373 
374  // map PRU memory into userspace
375  void* buffer0 = pru_map_memory();
376  void* buffer1 = buffer0 + buffer_size_bytes;
377 
378  // DATA FILE STORING
379 
380  // file header lead-in
381  struct rl_file_header file_header;
382  file_setup_lead_in(&(file_header.lead_in), conf);
383 
384  // channel array
385  int total_channel_count = file_header.lead_in.channel_bin_count +
386  file_header.lead_in.channel_count;
387  struct rl_file_channel file_channel[total_channel_count];
388  file_header.channel = file_channel;
389 
390  // complete file header
391  file_setup_header(&file_header, conf, file_comment);
392 
393  // store header
394  if (conf->file_format == BIN) {
395  file_store_header_bin(data_file, &file_header);
396  } else if (conf->file_format == CSV) {
397  file_store_header_csv(data_file, &file_header);
398  }
399 
400  // AMBIENT FILE STORING
401 
402  // file header lead-in
403  struct rl_file_header ambient_file_header;
404  // channel array
405  struct rl_file_channel ambient_file_channel[conf->ambient.sensor_count];
406 
407  if (conf->ambient.enabled == AMBIENT_ENABLED) {
408 
409  ambient_setup_lead_in(&(ambient_file_header.lead_in), conf);
410 
411  // channel array
412  ambient_file_header.channel = ambient_file_channel;
413 
414  // complete file header
415  ambient_setup_header(&ambient_file_header, conf, file_comment);
416 
417  // store header
418  file_store_header_bin(ambient_file, &ambient_file_header);
419  }
420 
421  // EXECUTION
422 
423  // write configuration to PRU memory
424  prussdrv_pru_write_memory(PRUSS0_PRU0_DATARAM, 0, (unsigned int*)&pru,
425  sizeof(struct pru_data_struct));
426 
427  // run SPI on PRU0
428  if (prussdrv_exec_program(0, PRU_CODE) < 0) {
429  rl_log(ERROR, "PRU code not found");
430  pru.state = PRU_OFF;
431  }
432 
433  // wait for first PRU event
434  if (pru_wait_event_timeout(PRU_EVTOUT_0, PRU_TIMEOUT) == ETIMEDOUT) {
435  // timeout occured
436  rl_log(ERROR, "PRU not responding");
437  pru.state = PRU_OFF;
438  }
439 
440  // clear event
441  prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
442 
443  void* buffer_addr;
444  struct time_stamp timestamp_monotonic;
445  struct time_stamp timestamp_realtime;
446  uint32_t buffers_lost = 0;
447  uint32_t buffer_samples_count; // number of samples per buffer
448  uint32_t num_files = 1; // number of files stored
449  uint8_t skipped_buffers = 0; // skipped buffers for ambient reading
450 
451  // sampling started
454 
455  // continuous sampling loop
456  for (uint32_t i = 0;
458  !(conf->mode == LIMIT && i >= number_buffers);
459  i++) {
460 
461  if (conf->file_format != NO_FILE) {
462 
463  // check if max file size reached
464  uint64_t file_size = (uint64_t)ftello(data_file);
465  uint64_t margin =
466  conf->sample_rate * sizeof(int32_t) * (NUM_CHANNELS + 1) +
467  sizeof(struct time_stamp);
468 
469  if (conf->max_file_size != 0 &&
470  file_size + margin > conf->max_file_size) {
471 
472  // close old data file
473  fclose(data_file);
474 
475  // determine new file name
476  char file_name[MAX_PATH_LENGTH];
477  char new_file_ending[MAX_PATH_LENGTH];
478  strcpy(file_name, conf->file_name);
479 
480  // search for last .
481  char target = '.';
482  char* file_ending = file_name;
483  while (strchr(file_ending, target) != NULL) {
484  file_ending = strchr(file_ending, target);
485  file_ending++; // Increment file_ending, otherwise we'll
486  // find target at the same location
487  }
488  file_ending--;
489 
490  // add file number
491  sprintf(new_file_ending, "_p%d", num_files);
492  strcat(new_file_ending, file_ending);
493  strcpy(file_ending, new_file_ending);
494 
495  // open new data file
496  data_file = fopen64(file_name, "w+");
497 
498  // update header for new file
499  file_header.lead_in.data_block_count = 0;
500  file_header.lead_in.sample_count = 0;
501 
502  // store header
503  if (conf->file_format == BIN) {
504  file_store_header_bin(data_file, &file_header);
505  } else if (conf->file_format == CSV) {
506  file_store_header_csv(data_file, &file_header);
507  }
508 
509  rl_log(INFO, "new datafile: %s", file_name);
510 
511  // AMBIENT FILE
512  if (conf->ambient.enabled == AMBIENT_ENABLED) {
513  // close old ambient file
514  fclose(ambient_file);
515 
516  // determine new file name
517  strcpy(file_name, conf->ambient.file_name);
518 
519  // search for last .
520  file_ending = file_name;
521  while (strchr(file_ending, target) != NULL) {
522  file_ending = strchr(file_ending, target);
523  file_ending++; // Increment file_ending, otherwise we'll
524  // find target at the same location
525  }
526  file_ending--;
527 
528  // add file number
529  sprintf(new_file_ending, "_p%d", num_files);
530  strcat(new_file_ending, file_ending);
531  strcpy(file_ending, new_file_ending);
532 
533  // open new ambient file
534  ambient_file = fopen64(file_name, "w+");
535 
536  // update header for new file
537  ambient_file_header.lead_in.data_block_count = 0;
538  ambient_file_header.lead_in.sample_count = 0;
539 
540  // store header
541  file_store_header_bin(ambient_file, &ambient_file_header);
542 
543  rl_log(INFO, "new ambient-file: %s", file_name);
544  }
545 
546  num_files++;
547  }
548  }
549 
550  // select current buffer
551  if (i % 2 == 0) {
552  buffer_addr = buffer0;
553  } else {
554  buffer_addr = buffer1;
555  }
556 
557  // select buffer size
558  if (i < number_buffers - 1 || pru.sample_limit % pru.buffer_size == 0) {
559  buffer_samples_count = pru.buffer_size; // full buffer size
560  } else {
561  buffer_samples_count =
562  pru.sample_limit % pru.buffer_size; // unfull buffer size
563  }
564 
565  // Wait for event completion from PRU
566  // only check for timeout on first buffer (else it does not work!)
567  if (i == 0) {
568  if (pru_wait_event_timeout(PRU_EVTOUT_0, PRU_TIMEOUT) ==
569  ETIMEDOUT) {
570  // timeout occurred
571  rl_log(ERROR, "ADC not responding");
572  break;
573  }
574  } else {
575  prussdrv_pru_wait_event(PRU_EVTOUT_0);
576  }
577 
578  // timestamp received data
579  create_time_stamp(&timestamp_realtime, &timestamp_monotonic);
580 
581  // adjust time with buffer latency
582  timestamp_realtime.nsec -= (uint64_t)1e9 / conf->update_rate;
583  if (timestamp_realtime.nsec < 0) {
584  timestamp_realtime.sec -= 1;
585  timestamp_realtime.nsec += (uint64_t)1e9;
586  }
587  timestamp_monotonic.nsec -= (uint64_t)1e9 / conf->update_rate;
588  if (timestamp_monotonic.nsec < 0) {
589  timestamp_monotonic.sec -= 1;
590  timestamp_monotonic.nsec += (uint64_t)1e9;
591  }
592 
593  // clear event
594  prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
595 
596  // check for overrun (compare buffer numbers)
597  uint32_t buffer_index = *((uint32_t*)buffer_addr);
598  if (buffer_index != i) {
599  buffers_lost += (buffer_index - i);
600  rl_log(WARNING,
601  "overrun: %d samples (%d buffer) lost (%d in total)",
602  (buffer_index - i) * pru.buffer_size, buffer_index - i,
603  buffers_lost);
604  i = buffer_index;
605  }
606 
607  // handle the buffer
608  file_handle_data(data_file, buffer_addr + 4, pru.sample_size,
609  buffer_samples_count, &timestamp_realtime,
610  &timestamp_monotonic, conf);
611 
612  // process data for web when enabled
613  if (conf->enable_web_server == 1) {
614  web_handle_data(web_data, sem_id, buffer_addr + 4, pru.sample_size,
615  buffer_samples_count, &timestamp_realtime, conf);
616  }
617 
618  // update and write header
619  if (conf->file_format != NO_FILE) {
620  // update the number of samples stored
621  file_header.lead_in.data_block_count += 1;
622  file_header.lead_in.sample_count +=
623  buffer_samples_count / avg_factor;
624 
625  if (conf->file_format == BIN) {
626  file_update_header_bin(data_file, &file_header);
627  } else if (conf->file_format == CSV) {
628  file_update_header_csv(data_file, &file_header);
629  }
630  }
631 
632  // handle ambient data
633  if (skipped_buffers + 1 >= conf->update_rate) { // always 1 Sps
634  if (conf->ambient.enabled == AMBIENT_ENABLED) {
635 
636  // fetch and write data
637  ambient_store_data(ambient_file, &timestamp_realtime,
638  &timestamp_monotonic, conf);
639 
640  // update and write header
641  ambient_file_header.lead_in.data_block_count += 1;
642  ambient_file_header.lead_in.sample_count +=
644  file_update_header_bin(ambient_file, &ambient_file_header);
645  }
646  skipped_buffers = 0;
647  } else {
648  skipped_buffers++;
649  }
650 
651  // update and write state
652  status.samples_taken += buffer_samples_count / avg_factor;
653  status.buffer_number = i + 1 - buffers_lost;
655 
656  // notify web clients
657  // Note: There is a possible race condition here, which might result in
658  // one web client not getting notified once, do we care?
659  if (conf->enable_web_server == 1) {
660  int num_web_clients = semctl(sem_id, WAIT_SEM, GETNCNT);
661  set_sem(sem_id, WAIT_SEM, num_web_clients);
662  }
663 
664  // print meter output
665  if (conf->mode == METER) {
666  meter_print_buffer(conf, buffer_addr + 4, pru.sample_size);
667  }
668  }
669 
670  // FILE FINISH (flush)
671  if (conf->file_format != NO_FILE && status.state != RL_ERROR) {
672  // print info
673  rl_log(INFO, "stored %llu samples to file", status.samples_taken);
674 
675  printf("Stored %llu samples to file.\n", status.samples_taken);
676 
677  fflush(data_file);
678  }
679 
680  // PRU FINISH (unmap memory)
681  pru_unmap_memory(buffer0);
682 
683  // WEBSERVER FINISH
684  // unmap shared memory
685  if (conf->enable_web_server == 1) {
686  remove_sem(sem_id);
687  shmdt(web_data);
688  }
689 
690  // METER FINISH
691  if (conf->mode == METER) {
692  meter_stop();
693  }
694 
695  // STATE
696  if (status.state == RL_ERROR) {
697  return FAILURE;
698  }
699 
700  return SUCCESS;
701 }
702 
708 void pru_stop(void) {
709 
710  // write OFF to PRU state (so PRU can clean up)
712 
713  // wait for interrupt (if no ERROR occured) and clear event
714  if (status.state != RL_ERROR) {
715  pru_wait_event_timeout(PRU_EVTOUT_0, PRU_TIMEOUT);
716  prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
717  }
718 }
719 
723 void pru_close(void) {
724 
725  // Disable PRU and close memory mappings
726  prussdrv_pru_disable(0);
727  prussdrv_exit();
728 }
int write_status(struct rl_status *status)
Definition: util.c:129
Limited sampling mode (limited by number of samples to take)
Definition: types.h:158
struct ringbuffer buffer[WEB_RING_BUFFER_COUNT]
Array of ring buffers for different time scales.
Definition: web.h:101
#define NUM_DIGITAL_INPUTS
Number of RocketLogger digital channels.
Definition: types.h:110
struct web_shm * web_create_shm(void)
Definition: web.c:47
rl_mode mode
Sampling mode.
Definition: types.h:251
#define WREG
Definition: pru.h:82
int pru_data_setup(struct pru_data_struct *pru, struct rl_conf *conf, uint32_t avg_factor)
Definition: pru.c:189
void file_handle_data(FILE *data_file, void *buffer_addr, uint32_t sample_data_size, uint32_t samples_count, struct time_stamp *timestamp_realtime, struct time_stamp *timestamp_monotonic, struct rl_conf *conf)
#define PRECISION_LOW
Definition: pru.h:139
void file_store_header_bin(FILE *data_file, struct rl_file_header *file_header)
#define FAILURE
Definition: types.h:78
#define SUCCESS
Definition: types.h:75
void file_update_header_bin(FILE *data_file, struct rl_file_header *file_header)
struct rl_file_lead_in lead_in
File header lead in (constant size)
Definition: rl_file.h:165
void meter_print_buffer(struct rl_conf *conf, void *buffer_addr, uint32_t sample_size)
Definition: meter.c:68
CSV format.
Definition: types.h:184
rl_pru_state state
Current PRU state.
Definition: pru.h:172
struct rl_status status
Current status of RocketLogger.
Definition: rl_server.c:71
int64_t sec
Seconds in UNIX time (UTC)
Definition: util.h:47
#define BUFFER1_SIZE
Size of 1s/div buffer.
Definition: web.h:60
#define RDATAC
Definition: pru.h:78
#define NUM_WEB_POINTS
Number of data points in web plot.
Definition: web.h:69
void * pru_map_memory(void)
Definition: pru.c:106
#define K64
Definition: pru.h:116
#define NUMBER_ADC_COMMANDS
Number of ADC commands.
Definition: pru.h:165
#define NUM_SEMS
Number of semaphores in set.
Definition: types.h:314
#define AMBIENT_DATA_BLOCK_SIZE
Definition: ambient.h:43
#define WAIT_SEM
Definition: types.h:326
void ambient_setup_lead_in(struct rl_file_lead_in *lead_in, struct rl_conf *conf)
Definition: ambient.c:101
void rl_log(rl_log_type type, const char *format,...)
Definition: log.c:39
#define CONFIG1DEFAULT
Definition: pru.h:121
#define K32
Definition: pru.h:115
#define SEM_KEY
Semaphore key (used for set creation)
Definition: types.h:312
int read_file_value(char filename[])
Definition: util.c:202
void meter_init(void)
Definition: meter.c:47
#define PRU_TIMEOUT
PRU time out in seconds.
Definition: pru.h:153
#define BUFFER10_SIZE
Size of 10s/div buffer.
Definition: web.h:62
int set_sem(int sem_id, int sem_num, int val)
Definition: sem.c:124
#define K1
Definition: pru.h:110
uint32_t num_channels
Number of channels sampled.
Definition: web.h:99
enum pru_state rl_pru_state
int ceil_div(int n, int d)
Definition: util.c:164
Limited sampling mode.
Definition: pru.h:160
struct rl_file_channel * channel
Channels definitions (binary and normal)
Definition: rl_file.h:171
#define GAIN1
Definition: pru.h:103
int digital_inputs
En-/disable digital inputs.
Definition: types.h:265
#define MAX_PATH_LENGTH
Maximum path length in characters.
Definition: types.h:102
uint64_t sample_count
Total sample count.
Definition: rl_file.h:117
void ambient_setup_header(struct rl_file_header *file_header, struct rl_conf *conf, char *comment)
Definition: ambient.c:160
uint16_t channel_bin_count
Binary channel count.
Definition: rl_file.h:132
void file_setup_header(struct rl_file_header *file_header, struct rl_conf *conf, char *comment)
#define PRECISION_HIGH
Definition: pru.h:138
int enable_web_server
En-/disable plots on web interface.
Definition: types.h:267
#define PRU_CODE
PRU binary file location.
Definition: pru.h:130
void file_update_header_csv(FILE *data_file, struct rl_file_header *file_header)
void file_setup_lead_in(struct rl_file_lead_in *lead_in, struct rl_conf *conf)
Definition: file_handling.c:60
#define CH4SET
Definition: pru.h:94
int sem_id
ID of semaphore set.
Definition: rl_server.c:53
Binary format.
Definition: types.h:185
#define DATA_SEM
Number of data semaphore in set (manages access to shared memory data)
Definition: types.h:323
rl_state state
State.
Definition: types.h:285
Continuous sampling mode.
Definition: pru.h:161
int create_sem(key_t key, int num_sems)
Definition: sem.c:46
uint64_t samples_taken
Number of samples taken.
Definition: types.h:289
#define I2L_INDEX
Definition: types.h:234
#define CONFIG1
Definition: pru.h:88
state
Definition: types.h:140
int remove_sem(int sem_id)
Definition: sem.c:59
struct web_shm * web_data
Pointer to shared memory data.
Definition: rl_server.c:55
void web_buffer_reset(struct ringbuffer *buffer, int element_size, int length)
Definition: web.c:101
uint32_t buffer_size
Shared buffer size.
Definition: pru.h:182
int sample_limit
Sample limit (0 for continuous)
Definition: types.h:259
Definition: types.h:247
#define NUM_CHANNELS
Maximum number of RocketLogger channels.
Definition: types.h:104
#define CHANNEL_ENABLED
Channel sampling enabled.
Definition: types.h:223
Warning.
Definition: types.h:201
#define CH2SET
Definition: pru.h:92
#define CONFIG3
Definition: pru.h:90
uint32_t number_commands
Number of ADC commands to send.
Definition: pru.h:186
#define BUFFER100_SIZE
Size of 100s/div buffer.
Definition: web.h:64
#define I1H_INDEX
Definition: types.h:229
#define PRU_DIG_SIZE
Size of PRU digital information in bytes.
Definition: types.h:114
#define CONFIG3DEFAULT
Definition: pru.h:123
uint32_t sample_limit
Samples to take (0 for continuous)
Definition: pru.h:184
void create_time_stamp(struct time_stamp *timestamp_realtime, struct time_stamp *timestamp_monotonic)
Definition: util.c:223
void web_handle_data(struct web_shm *web_data_ptr, int sem_id, void *buffer_addr, uint32_t sample_data_size, uint32_t samples_count, struct time_stamp *timestamp_realtime, struct rl_conf *conf)
Definition: web.c:201
#define CH3SET
Definition: pru.h:93
Running.
Definition: types.h:142
int channels[NUM_CHANNELS]
Channels to sample.
Definition: types.h:261
#define K2
Definition: pru.h:111
#define K8
Definition: pru.h:113
uint16_t channel_count
Analog channel count.
Definition: rl_file.h:135
void file_store_header_csv(FILE *data_file, struct rl_file_header *file_header)
#define CH5SET
Definition: pru.h:95
#define PRU_BUFFER_STATUS_SIZE
Size of PRU buffer status in bytes.
Definition: types.h:116
void ambient_store_data(FILE *ambient_file, struct time_stamp *timestamp_realtime, struct time_stamp *timestamp_monotonic, struct rl_conf *conf)
Definition: ambient.c:43
rl_file_format file_format
File format.
Definition: types.h:271
uint32_t buffer_number
Number of buffers taken.
Definition: types.h:291
#define WEB_RING_BUFFER_COUNT
Number of ring buffers in shared memory.
Definition: web.h:42
uint32_t sample_size
Sample size in shared memory.
Definition: pru.h:176
int update_rate
Data update rate.
Definition: types.h:257
void pru_stop(void)
Definition: pru.c:708
void pru_close(void)
Definition: pru.c:723
#define RESET
Definition: pru.h:74
#define SIZE_HIGH
Definition: pru.h:144
uint32_t precision
ADC precision (in bit)
Definition: pru.h:174
Definition: web.h:95
Error.
Definition: types.h:200
void meter_stop(void)
Definition: meter.c:60
int64_t nsec
Nanoseconds.
Definition: util.h:49
#define SDATAC
Definition: pru.h:79
int sample_rate
Sampling rate.
Definition: types.h:253
#define GAIN2
Definition: pru.h:104
No file.
Definition: types.h:183
void * pru_wait_event(void *voidEvent)
Definition: pru.c:56
#define I2H_INDEX
Definition: types.h:233
int pru_init(void)
Definition: pru.c:167
int pru_unmap_memory(void *pru_mmap)
Definition: pru.c:138
pthread_cond_t done
Notification variable.
Definition: pru.c:50
int buffer_sizes[WEB_RING_BUFFER_COUNT]
Buffer sizes for different time scales.
Definition: rl_server.c:74
uint32_t buffer0_location
Pointer to shared buffer 0.
Definition: pru.h:178
int pru_sample(FILE *data_file, FILE *ambient_file, struct rl_conf *conf, char *file_comment)
Definition: pru.c:296
Sampling.
Definition: types.h:151
rl_sampling sampling
Sampling state.
Definition: types.h:287
#define AMBIENT_ENABLED
Definition: types.h:211
int count_channels(int channels[NUM_CHANNELS])
Definition: util.c:80
uint32_t buffer1_location
Pointer to shared buffer 1.
Definition: pru.h:180
Information.
Definition: types.h:202
#define MIN_ADC_RATE
Minimal ADC sampling rate.
Definition: types.h:134
#define K4
Definition: pru.h:112
uint32_t commands[NUMBER_ADC_COMMANDS]
ADC commands to send.
Definition: pru.h:188
int pru_wait_event_timeout(unsigned int event, unsigned int timeout)
Definition: pru.c:79
#define I1L_INDEX
Definition: types.h:230
PRU off.
Definition: pru.h:159
uint32_t data_block_count
Number of data blocks stored in the file.
Definition: rl_file.h:114
#define CH6SET
Definition: pru.h:96
Meter mode (display current values in terminal)
Definition: types.h:160
#define MMAP_FILE
Memory map file.
Definition: pru.h:128
Error.
Definition: types.h:143
#define CH1SET
Definition: pru.h:91
void pru_set_state(rl_pru_state state)
Definition: pru.c:157
pthread_mutex_t waiting
PRU access mutex.
Definition: pru.c:47
#define DIGITAL_INPUTS_ENABLED
Digital input sampling ensabled.
Definition: types.h:242
#define K16
Definition: pru.h:114
#define CH7SET
Definition: pru.h:97