26 struct timespec spec_real;
27 struct timespec spec_monotonic;
30 int ret1 = clock_gettime(CLOCK_REALTIME, &spec_real);
31 int ret2 = clock_gettime(CLOCK_MONOTONIC_RAW, &spec_monotonic);
33 if( ret1 < 0 || ret2 < 0 ) {
38 time_real->
sec = (int64_t) spec_real.tv_sec;
39 time_real->
nsec = (int64_t) spec_real.tv_nsec;
40 time_monotonic->
sec = (int64_t) spec_monotonic.tv_sec;
41 time_monotonic->
nsec = (int64_t) spec_monotonic.tv_nsec;
55 fscanf(fp,
"%x", &mac_address[i]);
57 fscanf(fp,
":%x", &mac_address[i]);
72 uint16_t channel_bin_count = 0;
192 file_header->
comment = comment;
209 int comment_length = strlen(file_header->
comment);
211 if (comment_unaligned_bytes > 0) {
213 - comment_unaligned_bytes;
222 fwrite(file_header->
comment, comment_length, 1, data);
223 if (comment_unaligned_bytes > 0) {
239 fprintf(data,
"RocketLogger CSV File\n");
252 fprintf(data,
"Start Time,%s", ctime(&time));
253 fprintf(data,
"Comment,%s\n", file_header->
comment);
258 fprintf(data,
",%s", file_header->
channel[i].
name);
261 fprintf(data,
" [m");
264 fprintf(data,
" [u");
267 fprintf(data,
" [10n");
270 fprintf(data,
" [n");
273 fprintf(data,
" [10p");
302 fseek(data, 0, SEEK_END);
312 fprintf(data,
"RocketLogger CSV File\n");
317 fseek(data, 0, SEEK_END);
335 dest[ch_out++] = src[++ch_in];
343 dest[ch_out++] = src[ch_in++];
346 dest[ch_out++] = src[ch_in++];
349 dest[ch_out++] = src[ch_in++];
354 dest[ch_out++] = src[++ch_in];
362 dest[ch_out++] = src[ch_in++];
366 dest[ch_out++] = src[ch_in++];
369 dest[ch_out++] = src[ch_in++];
392 uint32_t num_bin_channels;
396 num_bin_channels = 0;
425 fwrite(&time_real,
sizeof(
struct time_stamp), 1, data);
426 fwrite(&time_monotonic,
sizeof(
struct time_stamp), 1, data);
429 time_t t = (time_t) time_real.
sec;
430 strcpy(value_char, ctime(&t));
431 value_char[strlen(value_char)-1] =
'\0';
432 fprintf(data,
"%s", value_char);
445 memset(bin_avg_data, 0,
sizeof(uint32_t) * num_bin_channels * WEB_RING_BUFFER_COUNT);
451 uint32_t num_web_channels = 0;
460 for(i=0; i<samples_buffer; i++){
467 strcpy(channel_data_char,
"\0");
471 uint8_t bin_adc1 = (*((int8_t *) (buffer_addr)));
472 uint8_t bin_adc2 = (*((int8_t *) (buffer_addr + 1)));
479 if(sample_size == 4) {
480 value = *( (int32_t *) (buffer_addr + sample_size*j) );
482 value = *( (int16_t *) (buffer_addr + sample_size*j) );
489 buffer_addr+=NUM_CHANNELS*sample_size;
495 uint32_t bin_channel_pos;
502 for(j=0; j<num_bin_channels; j++) {
503 if((bin_data & MASK) > 0) {
518 bin_data = bin_data | (valid1 << bin_channel_pos);
522 bin_data = bin_data | (valid2 << bin_channel_pos);
528 avg_valid[j][0] = avg_valid[j][0] & valid1;
529 avg_valid[j][1] = avg_valid[j][1] & valid2;
548 merge_currents(avg_valid[
BUF1_INDEX], &web_data[BUF1_INDEX][i/avg_length[BUF1_INDEX]][num_bin_channels], avg_data[BUF1_INDEX], conf);
551 for(j=0; j<num_bin_channels; j++) {
568 if (bin_channel_pos > 0) {
570 uint32_t temp_bin = 0;
571 for(j=0; j<num_bin_channels; j++) {
575 temp_bin = temp_bin | (avg_valid[
BUF1_INDEX][0] << j++);
578 temp_bin = temp_bin | (avg_valid[
BUF1_INDEX][1] << j++);
581 fwrite(&temp_bin,
sizeof(uint32_t), 1, data);
584 for(j=0; j<num_bin_channels; j++) {
586 strcat(channel_data_char,value_char);
589 sprintf(value_char,
", %d", avg_valid[
BUF1_INDEX][0]);
590 strcat(channel_data_char,value_char);
593 sprintf(value_char,
", %d", avg_valid[
BUF1_INDEX][1]);
594 strcat(channel_data_char,value_char);
602 int32_t tmp = (int32_t) avg_data[
BUF1_INDEX][j];
603 fwrite(&tmp,
sizeof(int32_t), 1, data);
607 sprintf(value_char,
",%d",(int32_t) avg_data[
BUF1_INDEX][j]);
608 strcat(channel_data_char, value_char);
610 strcat(channel_data_char,
"\n");
611 fprintf(data,
"%s", channel_data_char);
616 memset(avg_data[
BUF1_INDEX], 0,
sizeof(int64_t) * num_channels);
617 memset(bin_avg_data[BUF1_INDEX], 0,
sizeof(uint32_t) * num_bin_channels);
634 merge_currents(avg_valid[
BUF10_INDEX], &web_data[BUF10_INDEX][i/avg_length[BUF10_INDEX]][num_bin_channels], avg_data[BUF10_INDEX], conf);
638 for(j=0; j<num_bin_channels; j++) {
655 if (bin_channel_pos > 0) {
657 uint32_t temp_bin = 0;
658 for(j=0; j<num_bin_channels; j++) {
662 temp_bin = temp_bin | (avg_valid[
BUF10_INDEX][0] << j++);
665 temp_bin = temp_bin | (avg_valid[
BUF10_INDEX][1] << j++);
668 fwrite(&temp_bin,
sizeof(uint32_t), 1, data);
671 for(j=0; j<num_bin_channels; j++) {
673 strcat(channel_data_char,value_char);
676 sprintf(value_char,
", %d", avg_valid[
BUF10_INDEX][0]);
677 strcat(channel_data_char,value_char);
680 sprintf(value_char,
", %d", avg_valid[
BUF10_INDEX][1]);
681 strcat(channel_data_char,value_char);
690 fwrite(&tmp,
sizeof(int32_t), 1, data);
694 sprintf(value_char,
",%d",(int32_t) avg_data[
BUF10_INDEX][j]);
695 strcat(channel_data_char, value_char);
697 strcat(channel_data_char,
"\n");
698 fprintf(data,
"%s", channel_data_char);
703 memset(avg_data[
BUF10_INDEX], 0,
sizeof(int64_t) * num_channels);
704 memset(bin_avg_data[BUF10_INDEX], 0,
sizeof(uint32_t) * num_bin_channels);
720 merge_currents(avg_valid[
BUF100_INDEX], &web_data[BUF100_INDEX][i/avg_length[BUF100_INDEX]][num_bin_channels], avg_data[BUF100_INDEX], conf);
725 for(j=0; j<num_bin_channels; j++) {
738 if (bin_channel_pos > 0) {
740 uint32_t temp_bin = 0;
741 for(j=0; j<num_bin_channels; j++) {
745 temp_bin = temp_bin | (avg_valid[
BUF100_INDEX][0] << j++);
748 temp_bin = temp_bin | (avg_valid[
BUF100_INDEX][1] << j++);
751 fwrite(&temp_bin,
sizeof(uint32_t), 1, data);
754 for(j=0; j<num_bin_channels; j++) {
756 strcat(channel_data_char,value_char);
759 sprintf(value_char,
", %d", avg_valid[
BUF100_INDEX][0]);
760 strcat(channel_data_char,value_char);
763 sprintf(value_char,
", %d", avg_valid[
BUF100_INDEX][1]);
764 strcat(channel_data_char,value_char);
773 fwrite(&tmp,
sizeof(int32_t), 1, data);
777 sprintf(value_char,
",%d",(int32_t) avg_data[
BUF100_INDEX][j]);
778 strcat(channel_data_char, value_char);
780 strcat(channel_data_char,
"\n");
781 fprintf(data,
"%s", channel_data_char);
791 if (bin_channel_pos > 0) {
793 fwrite(&bin_data,
sizeof(uint32_t), 1, data);
797 for(j=0; j<bin_channel_pos; j++) {
798 sprintf(value_char,
", %d", (bin_data & MASK) > 1);
799 strcat(channel_data_char,value_char);
807 fwrite(channel_data,
sizeof(int32_t), num_channels, data);
811 sprintf(value_char,
",%d",channel_data[j]);
812 strcat(channel_data_char, value_char);
814 strcat(channel_data_char,
"\n");
815 fprintf(data,
"%s", channel_data_char);
834 web_data_ptr->
time = time_real.
sec*1000 + time_real.
nsec/1000000;
struct ringbuffer buffer[WEB_RING_BUFFER_COUNT]
Array of ring buffers for different time scales.
int offsets[NUM_CHANNELS]
Channel offsets (in bit)
int is_low_current(int index)
#define NUM_DIGITAL_INPUTS
Number of RocketLogger digital channels.
double scales[NUM_CHANNELS]
Channel scalings.
void store_header_csv(FILE *data, struct rl_file_header *file_header)
uint16_t data_size
Datum size in bytes (for voltage and current)
#define BUF10_INDEX
Index of 10s/div buffer.
uint16_t header_length
Total size of the header in bytes.
struct time_stamp start_time
Start time of the measurement in UNIX time, UTC.
#define MAC_ADDRESS_FILE
File to read MAC address.
struct rl_status status
Current status of RocketLogger.
void update_header_bin(FILE *data, struct rl_file_header *file_header)
void buffer_add(struct ringbuffer *buffer, int64_t *data)
int64_t sec
Seconds in UNIX time (UTC)
#define BINARY_MASK
Mask for binary inputs read from PRU.
int i1l_valid_channel
Global variable to determine i1l valid channel.
int i2l_valid_channel
Global variable to determine i2l valid channel.
#define BUFFER1_SIZE
Size of 1s/div buffer.
#define CSV_VALUE_LENGTH
Max length of a CSV value.
void rl_log(rl_log_type type, const char *format,...)
#define BUFFER10_SIZE
Size of 10s/div buffer.
int set_sem(int sem_id, int sem_num, int val)
uint32_t num_channels
Number of channels sampled.
int wait_sem(int sem_id, int sem_num, int time_out)
int digital_inputs
En-/disable digital inputs.
uint64_t sample_count
Total sample count.
uint16_t channel_bin_count
Binary channel count.
#define RL_FILE_MAGIC
File header magic number (ascii RLD)
int enable_web_server
En-/disable plots on web interface.
uint16_t file_version
File version number.
#define VALID_MASK
Mask for valid bit read from PRU.
int sem_id
ID of semaphore set.
#define CSV_LINE_LENGTH
Max length of a CSV file line.
#define DATA_SEM
Number of data semaphore in set (manages access to shared memory data)
#define BUF100_INDEX
Index of 100s/div buffer.
#define RL_SCALE_TEN_PICO
struct web_shm * web_data
Pointer to shared memory data.
#define NUM_I_CHANNELS
Maximum number of RocketLogger current channels.
rl_unit unit
Channel unit.
#define NUM_CHANNELS
Maximum number of RocketLogger channels.
#define CHANNEL_ENABLED
Channel sampling enabled.
#define BUFFER100_SIZE
Size of 100s/div buffer.
#define PRU_DIG_SIZE
Size of PRU digital information in bytes.
void merge_currents(uint8_t *valid, int64_t *dest, int64_t *src, struct rl_conf *conf)
#define NO_VALID_DATA
No additional range valid information available.
int channels[NUM_CHANNELS]
Channels to sample.
const char * digital_input_names[NUM_DIGITAL_INPUTS]
Digital input names.
uint16_t channel_count
Analog channel count.
#define BUF1_INDEX
Index of 1s/div buffer.
int64_t time
Time stamp of most recent datum (in UNIX time, UTC)
#define MAC_ADDRESS_LENGTH
MAC address length in bytes.
void store_header_bin(FILE *data, struct rl_file_header *file_header)
void setup_channels(struct rl_file_header *file_header, struct rl_conf *conf)
int is_current(int index)
uint32_t comment_length
Comment length.
rl_file_format file_format
File format.
uint32_t magic
File magic constant.
#define WEB_RING_BUFFER_COUNT
Number of ring buffers in shared memory.
int update_rate
Data update rate.
void create_time_stamp(struct time_stamp *time_real, struct time_stamp *time_monotonic)
uint32_t data_block_size
Size of the data blocks in the file in rows.
char name[RL_FILE_CHANNEL_NAME_LENGTH]
Channel name/description.
uint16_t sample_rate
Sampling rate of the measurement.
#define RL_FILE_COMMENT
Comment for file header.
#define RL_FILE_VERSION
File format version of current implementation.
void update_header_csv(FILE *data, struct rl_file_header *file_header)
int sample_rate
Sampling rate.
int32_t channel_scale
Channel scale (in power of ten, for voltage and current)
#define SEM_WRITE_TIME_OUT
Time out time in seconds, waiting on semaphore write.
uint16_t valid_data_channel
Link to channel valid data (for low-range current channels)
int count_channels(int channels[NUM_CHANNELS])
#define MIN_ADC_RATE
Minimal ADC sampling rate.
const char * valid_info_names[NUM_I_CHANNELS]
Valid channel names.
int8_t num_channels
Number of channels sampled.
uint32_t data_block_count
Number of data blocks stored in the file.
#define RL_FILE_COMMENT_ALIGNMENT_BYTES
Comment alignment in bytes.
void handle_data_buffer(FILE *data, void *buffer_addr, uint32_t sample_size, uint32_t samples_buffer, struct rl_conf *conf, int sem_id, struct web_shm *web_data_ptr)
void get_mac_addr(uint8_t mac_address[MAC_ADDRESS_LENGTH])
#define RL_SCALE_TEN_NANO
uint8_t mac_address[MAC_ADDRESS_LENGTH]
Instrument ID (mac address)
void setup_lead_in(struct rl_file_lead_in *lead_in, struct rl_conf *conf)
#define H_L_SCALE
Current high-low scale difference.
#define DIGITAL_INPUTS_ENABLED
Digital input sampling ensabled.
const char * channel_names[NUM_CHANNELS]
Channel names.
void setup_header(struct rl_file_header *file_header, struct rl_conf *conf)
struct rl_calibration calibration
Calibration data.