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