crusader |
Subversion Repositories: |
Compare with Previous - Blame - Download
/*
* crusader100_read_rss
*
* compile: gcc -Wall -D_DEBUG crusader100_read_rss.c -o crusader100_read_rss
*
* Licence: GNU GPL ver.2
*
* Changelog:
* 2007-01-27/Libor oprava cteni RSS<100, tj. dvoucifernych
* 2008-05-23/Libor zacatek prace na podpore Crusader Aggregator 100M
* 2008-06-07/Libor prvni verze se zakladni funkcnosti
* 2008-07-10/Libor cte krome hodnot registru vsechny veliciny
* 2008-07-13/Libor oprava neinicializovane promenne pro soucet RSS
*
*/
#include <assert.h>
#include <stdio.h> /* Standard input/output definitions */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> /* File control definitions */
#include <termios.h>
#include <unistd.h> /* UNIX standard function definitions */
#include <stdlib.h>
#include <limits.h> /* INT_MAX and others */
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <ctype.h> /* isdigit() a.s.o. */
#include <time.h>
static char *jmeno_seriaku = "";
static time_t cilovy_cas = 0;
static time_t cas_startu = 0;
/* baudrate settings are defined in <asm/termbits.h>, which is
included by <termios.h> */
#define BAUDRATE B38400
/* change this definition for the correct port */
//#define MODEMDEVICE "/dev/ttyS1"
//#define MODEMDEVICE "crusader.log"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1
#ifdef _DEBUG
# define DEBUG(level, fmt, args...) fprintf(stderr, fmt, ## args)
# define DBG(fmt, args...) DEBUG(L_DBG, "DEBUG: " fmt, ## args)
#else
# define DEBUG(level, fmt, args...)
# define DBG(fmt, args...)
#endif
#define L_ALERT -3
#define L_CRIT -2
#define L_ERR -1
#define L_DEFAULT 0
#define L_WARN 1
#define L_NOTICE 2
#define L_INFO 3
#define L_DBG 4
int otevri_seriak(char *devname)
{
int fd;
/*
Open modem device for reading and writing and not as controlling tty
because we don't want to get killed if linenoise sends CTRL-C.
*/
fd = open(devname, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0) { perror(devname); }
return fd;
}
int nastav_seriak(int fd, struct termios *oldtio)
{
struct termios newtio;
tcgetattr(fd, oldtio); /* save current serial port settings */
memset(&newtio, 0, sizeof(newtio)); /* clear struct for new port settings */
/*
BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
CRTSCTS : output hardware flow control (only used if the cable has
all necessary lines. See sect. 7 of Serial-HOWTO)
CS8 : 8n1 (8bit,no parity,1 stopbit)
CLOCAL : local connection, no modem contol
CREAD : enable receiving characters
*/
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
/*
IGNPAR : ignore bytes with parity errors
ICRNL : map CR to NL (otherwise a CR input on the other computer
will not terminate input)
otherwise make device raw (no other input processing)
*/
newtio.c_iflag = IGNPAR | ICRNL;
/*
Raw output.
*/
newtio.c_oflag = 0;
/*
ICANON : enable canonical input
disable all echo functionality, and don't send signals to calling program
*/
newtio.c_lflag = ICANON;
/*
initialize all control characters
default values can be found in /usr/include/termios.h, and are given
in the comments, but we don't need them here
*/
newtio.c_cc[VINTR] = 0; /* Ctrl-c */
newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */
newtio.c_cc[VERASE] = 0; /* del */
newtio.c_cc[VKILL] = 0; /* @ */
newtio.c_cc[VEOF] = 4; /* Ctrl-d */
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
newtio.c_cc[VSWTC] = 0; /* '\0' */
newtio.c_cc[VSTART] = 0; /* Ctrl-q */
newtio.c_cc[VSTOP] = 0; /* Ctrl-s */
newtio.c_cc[VSUSP] = 0; /* Ctrl-z */
newtio.c_cc[VEOL] = 0; /* '\0' */
newtio.c_cc[VREPRINT] = 0; /* Ctrl-r */
newtio.c_cc[VDISCARD] = 0; /* Ctrl-u */
newtio.c_cc[VWERASE] = 0; /* Ctrl-w */
newtio.c_cc[VLNEXT] = 0; /* Ctrl-v */
newtio.c_cc[VEOL2] = 0; /* '\0' */
/*
now clean the modem line and activate the settings for the port
*/
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW, &newtio);
return 0;
}
int restore_seriak(int fd, struct termios *stored_tio)
{
/* restore the old port settings */
tcsetattr(fd, TCSANOW, stored_tio);
return 0;
}
void print_usage()
{
printf("\nusage: seriak <jmeno seriaku> {<cilovy cas> | +<offset>}\n\n");
}
void check_params( int argc, char *argv[])
{
int relative = 0;
char *nptr = NULL, *endptr = NULL;
if ( argc != 3 || (argc == 3 && ( strcmp("-h", argv[1])==0 || strcmp("--help", argv[1])==0 )) ) {
print_usage();
exit(EXIT_FAILURE);
}
jmeno_seriaku = argv[1];
nptr = argv[2];
if ( argv[2][0] == '+' ) { /* relativni cas */
if ( strlen(argv[2]) < 1 ) {
print_usage();
exit(EXIT_FAILURE);
}
nptr++;
relative = 1;
}
cilovy_cas = strtol(argv[2], &endptr, 10);
#ifdef _DEBUG
fprintf (stderr, "arg[2]: %s, endptr: %p, cilovy_cas: %ld\n", argv[2], endptr, cilovy_cas);
#endif
if ( !(argv[2] != '\0' && *endptr == '\0') )
{
fprintf(stderr, "ERROR: spatny tvar ciloveho casu");
print_usage();
exit(EXIT_FAILURE);
}
if (relative) {
cilovy_cas += cas_startu;
}
}
/**
* Hleda zda se v prijimacim bufferu buff naleza ocekavany retezec exp_res.
* @param buf pointer na prijimaci buffer
* @param buflen delka prijimaciho bufferu
* @param exp_res ocekavany vysledek, ktery hledame ve vstupnim bufferu
* @return 0 kdyz je to OK, jinak 1.
*
*/
int check_response(char *buf, int buflen, char *exp_res)
{
return 0;
}
/**
* vypise na stderr obsah daneho bufferu jako text i jako hexakody.
* misto tisknutelnych znaku se vypisuje tecka
* @param buf ukazatel na buffer
* @param bufsize velikost bufferu
* @param pocet pocet bajtu, ktere se maji vypsat
*/
void print_debug_buffer(char *buf, size_t bufsize, size_t pocet)
{
time_t cas;
int i;
assert(bufsize >= 0);
assert(buf != NULL);
DBG("print_debug_buffer(bufsize=%d, pocet=%d)\n", bufsize, pocet);
cas = time(0);
if (pocet > bufsize) {
fprintf(stderr, "prilis maly buffer, snizuji pocet = bufsize\n");
pocet = bufsize;
}
fprintf(stderr, "DEBUG: cas: %ld, buf: '", cas);
for ( i = 0; i < pocet; ++i )
{
if (buf[i] >= ' ') {
fprintf(stderr, "%c", buf[i]);
} else {
fprintf(stderr, ".");
}
}
fprintf(stderr, "' hex: ");
for ( i = 0; i < pocet; ++i ) {
fprintf(stderr, "%02x ", buf[i]);
}
fprintf(stderr, "\n");
}
// TODO check HUGE_VAL, ERANGE, see strtod(3)
int get_double(char *str, int len, double *value)
{
double v;
char *eptr;
DBG("get_double(str='%.*s', len=%d)\n", len, str, len);
eptr = NULL;
v = strtod(str, &eptr);
if (*eptr == '\0') {
DBG("get_double: value = %6.2f\n", v);
*value = v;
return 0;
}
else {
DBG("get_double: error in conversion\n");
*value = 0;
return -1;
}
}
int get_long(char *str, int len, long *value)
{
long v;
char *eptr;
DBG("get_long(str='%.*s', len=%d)\n", len, str, len);
eptr = NULL;
v = strtol(str, &eptr, 10);
if (*eptr == '\0') {
DBG("get_long: value = %ld\n", v);
*value = v;
return 0;
}
else {
DBG("get_long: error in conversion\n");
*value = 0;
return -1;
}
}
#define CRS_NAMERENO_RSS 1 << 0
#define CRS_NAMERENO_P_LSR 1 << 1
#define CRS_NAMERENO_I_BIAS 1 << 2
#define CRS_NAMERENO_U_APD 1 << 3
#define CRS_NAMERENO_T_APD 1 << 4
#define CRS_NAMERENO_T_CPU 1 << 5
#define CRS_NAMERENO_L 1 << 6
#define CRS_NAMERENO_HEAT 1 << 7
typedef enum {
RSS_MIN,
RSS_MAX,
RSS_SUM,
RSS_CNT,
RSS_LAST
} rss_names_t;
/**
* Struktura obsahujici prectene udaje. Pokud byl behem merici periody nektery udaj precten vicekrat,
* obsahuje naposledy prectenou hodnotu. To se netyka RSS (Received Signal Strength), kde se uchovava
* ctene minimum, maximim, soucet a pocet ctenych hodnot. Ze souctu se pak pocita prumerna hodnota.
*
*/
typedef struct {
int namereno; /// bitove pole obsahujici informaci o tom, ktere hodnoty jsou skutecne zmerene
long rss[RSS_LAST]; /// bez prefixu
double laser_power; /// Pl [mW], vykon laseru
double laser_bias; /// Ib [mA], bias proud laserem
double apd_voltage; /// Ua [V]
double apd_temp; /// Ta [C]
double apd_ureg; /// Ur bezrozmerne, hodnota registru menice APD
double cpu_temp; /// T [C]
int da_reg[2]; /// L bezrozmerne, hodnoty registru D/A prevodniku
} crusader_meas_t;
void clear_value(char* varr, size_t va_size)
{
memset(varr, 0, va_size);
}
#define KONECNY_STAV 0x1000
/*
* Stavy prijimaciho automatu
*/
typedef enum {
ST_START, /// pocatecni stav automatu, zacina parsovani radky, obvykle po ST_NL nebo kdyz se ocekavaji dalsi hodnoty na radce
ST_NL, /// '\n' new line, synchronizuje automat, prechoazi do ST_START
ST_KOMENTAR, /// NL -> '!', oznacuje komentar do dalsiho NL. Komentar '!OK' ma specialni vyznam
ST_PLUS,
ST_RSS, /// NL -> ' ', zacina cteni RSS, akceptuje cislice 0-9, jiny znak trigruje prechod do ST_KOMENTAR,
/// tj. ignorujeme RSS protistrany a bargraf
ST_U,
ST_U_A,
ST_U_APD,
ST_U_R,
ST_U_REG,
ST_T,
ST_T_A,
ST_T_APD,
ST_T_CPU,
ST_P,
ST_PL,
ST_PLASER,
ST_I,
ST_IB,
ST_IBIAS,
ST_H,
ST_L,
ST_L1,
ST_L2,
ST_ERROR = KONECNY_STAV | 500
} state_t;
int sezer_seriak(int seriak)
{
ssize_t precteno;
time_t cas = 0;
int chyba;
static char buf[129];
static size_t bufsize = sizeof(buf);
int i = 0;
char *p;
DBG("sezer_seriak(fd=%d)\n", seriak);
precteno = read(seriak, buf, bufsize-1);
DBG("sezer_seriak: precteno = %d\n", precteno);
DBG("sezer_seriak: cas = %lu, cilovy_cas = %lu\n", cas, cilovy_cas);
while (precteno && cas < cilovy_cas) {
i++;
cas = time(0);
DBG("sezer_seriak: i=%2d precteno = %d\n", i, precteno);
DBG("sezer_seriak: i=%2d cas = %lu, cilovy_cas = %lu\n", i, cas, cilovy_cas);
if (precteno < 0) {
DBG("if (precteno < 0)...\n");
chyba = errno;
if (chyba == EAGAIN) {
fprintf(stderr, "continuing...\n");
sleep(1);
goto loop_end;
}
perror("chyba cteni: ");
fprintf(stderr, "chyba = %d\n", chyba);
fprintf(stderr, "EAGAIN = %d\n", EAGAIN);
goto err;
}
if (precteno > 0) {
for (p = buf; p < buf+precteno; p++) {
if (*p == '+') goto end;
}
}
#ifdef _DEBUG
print_debug_buffer(buf, bufsize, precteno);
#endif
loop_end:
precteno = read(seriak, buf, bufsize-1);
}
end:
DBG("sezer_seriak(), done\n");
return 0;
err:
DBG("sezer_seriak(), fail\n");
return -1;
}
int main(int argc, char *argv[])
{
struct termios old_tio;
int seriak = -1;
int chyba;
ssize_t precteno;
ssize_t ibuflen;
char buf[129];
size_t bufsize = sizeof(buf);
time_t cas = 0;
char *p;
crusader_meas_t mereni;
mereni.rss[RSS_MIN] = INT_MAX;
mereni.rss[RSS_MAX] = 0;
mereni.rss[RSS_CNT] = 0;
mereni.rss[RSS_SUM] = 0;
mereni.laser_power = 0;
mereni.laser_bias = 0;
mereni.apd_voltage = 0;
mereni.apd_temp = 0;
mereni.cpu_temp = 0;
long rss_avg;
state_t state, next_state;
int vidx; /// index cislice hodnoty (value)
char val_arr[16];
char state_text[128];
int state_text_len;
int clear_state_text = 1;
long int long_val;
double double_val;
long long loopcnt = 0;
int posledni_kus = 0;
cas_startu = time(0);
DEBUG(L_INFO, "Cas startu: %ld - %s", cas_startu, ctime(&cas_startu));
check_params(argc, argv);
DEBUG(L_INFO, "Cilovy cas: %ld - %s", cilovy_cas, ctime(&cilovy_cas));
seriak = otevri_seriak(jmeno_seriaku);
if ( seriak == -1 )
{
char msg[256];
snprintf(msg, sizeof(msg)-1, "Nejde otevrit seriak (%s)", jmeno_seriaku);
msg[255] = '\0';
perror(msg);
free(msg);
goto error1;
}
nastav_seriak(seriak, &old_tio);
DBG("MAIN: write 'Z'\n");
write(seriak, "Z\r", 2);
sezer_seriak(seriak);
DBG("MAIN: write 'E0'\n");
write(seriak, "E0\r", 3);
sezer_seriak(seriak);
write(seriak, "#1\r", 3);
clear_value(val_arr, sizeof(val_arr));
state_text_len = 0;
memset(state_text, 0, sizeof(state_text));
clear_state_text = 1;
for ( ; cas < cilovy_cas && posledni_kus == 0; cas = time(0) )
{
precteno = read(seriak, buf, bufsize-1); /* one character less for terminating '\0' */
if (precteno < 0) {
chyba = errno;
if (chyba == EAGAIN) {
DEBUG(L_INFO, "continuing...\n");
sleep(1);
continue;
}
perror("chyba cteni: ");
fprintf(stderr, "chyba = %d\n", chyba);
fprintf(stderr, "EAGAIN = %d\n", EAGAIN);
goto error1;
}
// pouze pri cteni souboru
// if (precteno != bufsize-1)
// posledni_kus = 1;
#ifdef _DEBUG
fprintf(stderr, "Precteno: %d\n", precteno);
print_debug_buffer(buf, bufsize, precteno);
#endif
ibuflen = precteno;
p = buf;
state = ST_START; /// zaciname s cistym stitem, tj. jakoby na novem radku
next_state = ST_ERROR; /// pokud se nic nestane, skoncime s chybou
while (ibuflen > 0)
{
loopcnt++;
assert(state_text_len >= 0);
assert(state_text_len < sizeof(state_text));
state_text[state_text_len] = *p;
state_text_len++;
switch (state) {
case ST_START:
DBG("ST_START\n");
case ST_NL:
DBG("ST_NL\n");
vidx = 0;
switch (*p) {
case '!':
next_state = ST_KOMENTAR;
break;
case '+':
next_state = ST_PLUS;
break;
case 0x0a:
next_state = ST_NL;
break;
default:
next_state = ST_ERROR;
}
break;
case ST_ERROR:
DBG("ST_ERROR\n");
case ST_KOMENTAR:
DBG("ST_KOMENTAR\n");
if (*p == 0x0a)
next_state = ST_NL;
else
next_state = ST_KOMENTAR;
break;
case ST_PLUS:
DBG("ST_PLUS\n");
switch (*p) {
case ' ':
next_state = ST_RSS;
break;;
case 'U':
next_state = ST_U;
break;
case 'P':
next_state = ST_P;
break;
case 'T':
next_state = ST_T;
break;
case 'I':
next_state = ST_I;
break;
case 'L':
next_state = ST_L;
break;
case 'H':
next_state = ST_H;
break;
default:
next_state = ST_ERROR;
}
break;
case ST_RSS:
DBG("ST_RSS\n");
// ignore spaces
if (*p == ' ' && state_text_len == 1) {
clear_state_text = 1;
break;
}
// do not read rss yet, wait for space, grr!!!
// TODO je potreba vyresit cteni RSS, ktera ma na obou stranach mezeru
// takze ji neni mozne jednoduse bezstavove parsovat
// resenim bude asi dat nove stavy RSSM, M jako mezera,
// RSSMC, C jako cifra a RSSMCM, M jako mezera.
// kdyz se precte druha mezera, prevede se state_text string na cislo
if (isdigit(*p)) break;
DBG("ST_RSS: *p = '%c'\n", *p);
state_text[state_text_len-1] = '\0';
if (get_long(state_text, state_text_len, &long_val) < 0) {
fprintf(stderr, "ERROR in conversion, exiting.\n");
exit(1);
}
mereni.rss[RSS_SUM] += long_val;
mereni.rss[RSS_CNT]++;
if (long_val < mereni.rss[RSS_MIN]) mereni.rss[RSS_MIN] = long_val;
if (long_val > mereni.rss[RSS_MAX]) mereni.rss[RSS_MAX] = long_val;
DBG("RSS: cnt=%ld curr=%ld min=%ld max=%ld sum=%ld\n", mereni.rss[RSS_CNT], long_val, mereni.rss[RSS_MIN], mereni.rss[RSS_MAX], mereni.rss[RSS_SUM]);
next_state = ST_KOMENTAR;
break;
case ST_PLASER:
DBG("ST_PLASER\n");
// ignore spaces
if (*p == ' ' && state_text_len == 1) {
clear_state_text = 1;
break;
}
// hodnota je float
// TODO kontrolovat pritomnost pouze jedne tecky
if (isdigit(*p) || *p == '.') break;
DBG("ST_PLASER: *p = '%c'\n", *p);
state_text[state_text_len-1] = '\0';
if (get_double(state_text, state_text_len, &double_val) < 0) {
fprintf(stderr, "ERROR in conversion, exiting.\n");
exit(1);
}
mereni.laser_power = double_val;
// jednotky ignorujeme, stejne to jsou vzdy mW
next_state = ST_KOMENTAR;
break;
case ST_IBIAS:
DBG("ST_IBIAS\n");
// ignore spaces
if (*p == ' ' && state_text_len == 1) {
clear_state_text = 1;
break;
}
// hodnota je float
// TODO kontrolovat pritomnost pouze jedne tecky
if (isdigit(*p) || *p == '.') break;
DBG("ST_IBIAS: *p = '%c'\n", *p);
state_text[state_text_len-1] = '\0';
if (get_double(state_text, state_text_len, &double_val) < 0) {
fprintf(stderr, "ERROR in conversion, exiting.\n");
exit(1);
}
mereni.laser_bias = double_val;
// jednotky ignorujeme, stejne to jsou vzdy mA
next_state = ST_KOMENTAR;
break;
case ST_T_APD:
DBG("ST_T_APD\n");
// ignore spaces
if (*p == ' ' && state_text_len == 1) {
clear_state_text = 1;
break;
}
// hodnota je float
if (isdigit(*p) || *p == '.') break;
DBG("ST_T_APD: *p = '%c'\n", *p);
state_text[state_text_len-1] = '\0';
if (get_double(state_text, state_text_len, &double_val) < 0) {
fprintf(stderr, "ERROR in conversion, exiting.\n");
exit(1);
}
mereni.apd_temp = double_val;
// jednotky ignorujeme, stejne to jsou vzdy mA
next_state = ST_KOMENTAR;
break;
case ST_T_CPU:
DBG("ST_T_CPU\n");
// ignore spaces
if (*p == ' ' && state_text_len == 1) {
clear_state_text = 1;
break;
}
// hodnota je float
if (isdigit(*p) || *p == '.') break;
DBG("ST_T_CPU: *p = '%c'\n", *p);
state_text[state_text_len-1] = '\0';
if (get_double(state_text, state_text_len, &double_val) < 0) {
fprintf(stderr, "ERROR in conversion, exiting.\n");
exit(1);
}
mereni.cpu_temp = double_val;
// jednotky ignorujeme, stejne to jsou vzdy mA
next_state = ST_KOMENTAR;
break;
case ST_U_APD:
DBG("ST_U_APD\n");
// ignore spaces
if (*p == ' ' && state_text_len == 1) {
clear_state_text = 1;
break;
}
// hodnota je float
if (isdigit(*p) || *p == '.') break;
DBG("ST_U_APD: *p = '%c'\n", *p);
state_text[state_text_len-1] = '\0';
if (get_double(state_text, state_text_len, &double_val) < 0) {
fprintf(stderr, "ERROR in conversion, exiting.\n");
exit(1);
}
mereni.apd_voltage = double_val;
// jednotky ignorujeme, stejne to jsou vzdy mA
next_state = ST_KOMENTAR;
break;
case ST_U:
DBG("ST_U\n");
switch (*p) {
case 'a':
next_state = ST_U_A;
break;
case 'r':
next_state = ST_U_R;
break;
default:
next_state = ST_ERROR;
}
break;
case ST_P:
DBG("ST_P\n");
switch (*p) {
case 'l':
next_state = ST_PL;
break;
default:
next_state = ST_ERROR;
}
break;
case ST_PL:
DBG("ST_PL\n");
switch (*p) {
case '=':
next_state = ST_PLASER;
break;
default:
next_state = ST_ERROR;
}
break;
case ST_T:
DBG("ST_T\n");
switch (*p) {
case '=':
next_state = ST_T_CPU;
break;
case 'a':
next_state = ST_T_A;
break;
default:
next_state = ST_ERROR;
}
break;
case ST_T_A:
DBG("ST_T_TA\n");
switch (*p) {
case '=':
next_state = ST_T_APD;
break;
default:
next_state = ST_ERROR;
}
break;
case ST_I:
DBG("ST_I\n");
switch (*p) {
case 'b':
next_state = ST_IB;
break;
default:
next_state = ST_ERROR;
}
break;
case ST_IB:
DBG("ST_IB\n");
switch (*p) {
case '=':
next_state = ST_IBIAS;
break;
default:
next_state = ST_ERROR;
}
break;
case ST_U_A:
DBG("ST_U_A\n");
switch (*p) {
case '=':
next_state = ST_U_APD;
break;
default:
next_state = ST_ERROR;
}
break;
case ST_U_R:
DBG("ST_U_R\n");
switch (*p) {
case '=':
next_state = ST_U_REG;
break;
default:
next_state = ST_ERROR;
}
break;
case ST_L:
DBG("ST_L\n");
case ST_H:
DBG("ST_H\n");
next_state = ST_KOMENTAR;
break;
default:
DBG("default\n");
/* nyni H, L */
next_state = ST_ERROR;
}
if (state != next_state || clear_state_text == 1) {
state_text_len = 0;
clear_state_text = 0;
}
state = next_state;
ibuflen--;
p++;
#ifdef _DEBUG
fprintf(stderr, "state_text: ");
print_debug_buffer(state_text, sizeof(state_text), state_text_len);
#endif
}
loopcnt++;
}
// restore_seriak(seriak, &old_tio);
close(seriak);
rss_avg = mereni.rss[RSS_CNT]>0 ? mereni.rss[RSS_SUM]/mereni.rss[RSS_CNT] : -1;
fprintf(stderr, "Number of received valid values: %ld\n", mereni.rss[RSS_CNT]);
fprintf(stderr, "Total sum of RSS: %ld\n", mereni.rss[RSS_SUM]);
fprintf(stderr, "Average RSS: %ld\n", rss_avg);
fprintf(stderr, "Maximum RSS: %ld\n", mereni.rss[RSS_MAX]);
fprintf(stderr, "Minimum RSS: %ld\n", mereni.rss[RSS_MIN]);
fprintf(stderr, "LASER power: %6.2f\n", mereni.laser_power);
fprintf(stderr, "LASER bias: %6.2f\n", mereni.laser_bias);
fprintf(stderr, "APD voltage: %6.2f\n", mereni.apd_voltage);
fprintf(stderr, "APD temp: %6.2f\n", mereni.apd_temp);
fprintf(stderr, "CPU temp: %6.2f\n", mereni.cpu_temp);
fprintf(stderr, "loops: %lld\n", loopcnt);
printf("%ld %ld %ld %ld %6.2f %6.2f %6.2f %6.2f %6.2f\n", mereni.rss[RSS_CNT], rss_avg, mereni.rss[RSS_MAX], mereni.rss[RSS_MIN], mereni.laser_power, mereni.laser_bias, mereni.apd_voltage, mereni.apd_temp, mereni.cpu_temp);
return EXIT_SUCCESS;
error1:
if (seriak >= 0) {
restore_seriak(seriak, &old_tio);
close(seriak);
}
return EXIT_FAILURE;
}