RocketLogger  1.1.6
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 
405  if (conf->ambient.enabled == AMBIENT_ENABLED) {
406 
407  ambient_setup_lead_in(&(ambient_file_header.lead_in), conf);
408 
409  // allocate channel array
410  ambient_file_header.channel =
411  malloc(conf->ambient.sensor_count * sizeof(struct rl_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 = fopen64(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 = fopen64(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  // flush ambient data and cleanup file header
671  if (conf->ambient.enabled == AMBIENT_ENABLED) {
672  fflush(ambient_file);
673  free(ambient_file_header.channel);
674  }
675 
676  if (conf->file_format != NO_FILE && status.state != RL_ERROR) {
677  fflush(data_file);
678  rl_log(INFO, "stored %llu samples to file", status.samples_taken);
679  printf("Stored %llu samples to file.\n", status.samples_taken);
680  }
681 
682  // PRU FINISH (unmap memory)
683  pru_unmap_memory(buffer0);
684 
685  // WEBSERVER FINISH
686  // unmap shared memory
687  if (conf->enable_web_server == 1) {
688  remove_sem(sem_id);
689  shmdt(web_data);
690  }
691 
692  // METER FINISH
693  if (conf->mode == METER) {
694  meter_stop();
695  }
696 
697  // STATE
698  if (status.state == RL_ERROR) {
699  return FAILURE;
700  }
701 
702  return SUCCESS;
703 }
704 
710 void pru_stop(void) {
711 
712  // write OFF to PRU state (so PRU can clean up)
714 
715  // wait for interrupt (if no ERROR occured) and clear event
716  if (status.state != RL_ERROR) {
717  pru_wait_event_timeout(PRU_EVTOUT_0, PRU_TIMEOUT);
718  prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
719  }
720 }
721 
725 void pru_close(void) {
726 
727  // Disable PRU and close memory mappings
728  prussdrv_pru_disable(0);
729  prussdrv_exit();
730 }
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)
struct rl_ambient ambient
Ambient conf.
Definition: types.h:277
#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
int enabled
Definition: types.h:213
#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
int sensor_count
Definition: types.h:214
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
char file_name[MAX_PATH_LENGTH]
Data file name.
Definition: types.h:275
#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:710
void pru_close(void)
Definition: pru.c:725
#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
char file_name[MAX_PATH_LENGTH]
Definition: types.h:216
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
uint64_t max_file_size
Maximum data file size.
Definition: types.h:273
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