423 lines
11 KiB
C
423 lines
11 KiB
C
/*
|
|
* Äàííûé ïðèìåð äåìîíñòðèðóåò âîçìîæíîñòü âûâîäà îòñ÷åòîâ ñèãíàëà èç ôàéëà íà
|
|
* âûâîä â ìîäóëü E16 / LTA37 / E502 / L502 (ââîä íå èñïîëüçóåòñÿ âîîáùå).
|
|
*
|
|
* Ëþáîå ÷èñëî âî âõîäíîì ôàéëå òðàêòóåòñÿ êàê çíà÷åíèå â Âîëüòàõ âûõîäà ÖÀÏ
|
|
* Äâà ÷èñëà ðàçäåëåííûå ëþáûì ñèìâîëîì êðîìå ïåðåâîäà ñòðîêè òðàêòóþòñÿ êàê çíà÷åíèÿ äâóõ êàíàëîâ ÖÀÏ
|
|
* Ïåðåâîä ñòðîêè òàðàêòóåòñÿ êàê ïåðåõîä ê ñëåäóþùåìó îòñ÷åòó
|
|
*/
|
|
|
|
#include "l502api.h"
|
|
#include "e502api.h"
|
|
|
|
#include <locale.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
#include "dev_funcs.h"
|
|
#include "timespec_funcs.h"
|
|
|
|
#ifndef _WIN32
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
//#define DEBUG
|
|
#ifdef DEBUG
|
|
#define dbg_printf(...) fprintf(stderr, __VA_ARGS__)
|
|
#else
|
|
#define dbg_printf(...)
|
|
#endif
|
|
|
|
|
|
/* ïðèçíàê íåîáõîäèìîñòè çàâåðøèòü ñáîð äàííûõ */
|
|
static volatile int f_out = 0;
|
|
|
|
#define DAC_BUF_SIZE (1024 * 1024)
|
|
/* òàéìàóò íà îòïðàâêó áëîêà (ìñ) */
|
|
#define SEND_TOUT 500
|
|
|
|
double dac_freq = 200000;
|
|
// çàäåðæêà âûâîäà â ñåêóíäàõ ìåæäó öèêëàìè
|
|
double cycle_delay;
|
|
|
|
// Âûâîäèòü èç ôàéëà öèêëè÷åñêè
|
|
int cycle_mode = 1;
|
|
|
|
#ifndef _WIN32
|
|
/* Îáðàáîò÷èê ñèãíàëà çàâåðøåíèÿ äëÿ Linux */
|
|
static void f_abort_handler(int sig) {
|
|
f_out = 1;
|
|
}
|
|
#endif
|
|
|
|
int32_t f_setup_params(t_x502_hnd hnd) {
|
|
int32_t err;
|
|
|
|
X502_SetSyncMode(hnd, X502_SYNC_INTERNAL);
|
|
X502_StreamsStop(hnd);
|
|
X502_StreamsDisable(hnd, X502_STREAM_ALL_IN|X502_STREAM_ALL_OUT);
|
|
|
|
err = X502_SetOutFreq(hnd, &dac_freq);
|
|
if (err) {
|
|
fprintf(stderr, "X502_SetOutFreq err=%d dout_freq = %.1f\n", err, dac_freq);
|
|
}
|
|
|
|
/* çàïèñûâàåì íàñòðîéêè â ìîäóëü */
|
|
if (err == X502_ERR_OK) {
|
|
err = X502_Configure(hnd, 0);
|
|
}
|
|
|
|
if (err == X502_ERR_OK) {
|
|
/* âûâîäèì ðåàëüíî óñòàíîâëåííûå çíà÷åíèÿ - òå ÷òî âåðíóëè ôóíêöèè */
|
|
fprintf(stderr, "Óñòàíîâëåííàÿ ÷àñòîòà ÖÀÏ: %0.0f Hz\n", dac_freq);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
void parse_params(int argc, char **argv) {
|
|
for (int i = 1; (int)i < argc - 1; i++) {
|
|
if (sscanf(argv[i], "dac_freq:%lf", &dac_freq) == 1) {
|
|
fprintf(stderr, "Çàïðàøèâàåìàÿ ÷àñòîòà ÖÀÏ: %0.0f Hz\n", dac_freq);
|
|
} else
|
|
if (sscanf(argv[i], "cycle_delay:%lf", &cycle_delay) == 1) {
|
|
fprintf(stderr, "cycle_delay=%lf sec\n", cycle_delay);
|
|
} else
|
|
if (strcmp(argv[i], "once") == 0) {
|
|
cycle_mode = 0;
|
|
fprintf(stderr, "cycle_mode=0\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
#define BUF_SIZE (64 * 1024)
|
|
|
|
#define CH_ENABLED 2
|
|
|
|
void show_help(char *name) {
|
|
fprintf(stderr,
|
|
"Usage: %s [dac_freq:500000] [cycle_delay:0.0001] [once] input.file\n"
|
|
"\tdac_freq: DAC freq in Hz\n"
|
|
"\tcycle_delay: delay DAC output in seconds before new cycle start\n"
|
|
"Select module by ip: %s [E16:192.168.0.1] [dac_freq:500000] [once] input.file\n"
|
|
"\nTest input file (2 DAC):\n"
|
|
"\t0.000000; -5.000000\n"
|
|
"\t1.000000; -4.000000\n"
|
|
"\t2.000000; -3.000000\n"
|
|
"\t3.000000; -2.000000\n"
|
|
"\t4.000000; -1.000000\n"
|
|
"\t5.000000; -0.000000\n"
|
|
"\t4.000000; -1.000000\n"
|
|
"\t3.000000; -2.000000\n"
|
|
"\t2.000000; -3.000000\n"
|
|
"\t1.000000; -4.000000\n"
|
|
, name, name);
|
|
}
|
|
|
|
int out_dac_from_file(t_x502_hnd hnd, FILE* f);
|
|
|
|
int main(int argc, char **argv) {
|
|
int32_t err = 0;
|
|
uint32_t ver;
|
|
t_x502_hnd hnd = NULL;
|
|
FILE* f;
|
|
#ifndef _WIN32
|
|
struct sigaction sa;
|
|
memset(&sa, 0, sizeof(sa));
|
|
/*  ÎÑ Linux óñòàíàâëèâàåì ñâîé îáðàáîò÷èê íà ñèãíàë çàêðûòèÿ,
|
|
÷òîáû çàâåðøèòü ñáîð êîððåêòíî */
|
|
sa.sa_handler = f_abort_handler;
|
|
sigaction(SIGTERM, &sa, NULL);
|
|
sigaction(SIGINT, &sa, NULL);
|
|
sigaction(SIGABRT, &sa, NULL);
|
|
#endif
|
|
#ifdef _WIN32
|
|
/* óñòàíàâëèâàåì ëîêàëü, ÷òîáû ìîæíî áûëî âûâîäèòü ïî-ðóññêè â CP1251 áåç ïåðåâîäà â OEM */
|
|
setlocale(LC_CTYPE, "");
|
|
#endif
|
|
|
|
if (argc == 1) {
|
|
show_help(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
/********** Ïîëó÷åíèå ñïèñêà óñòðîéñòâ è âûáîð, ñ êàêèì áóäåì ðàáîòàòü ******************/
|
|
hnd = select_dev_from_list(argc, argv, 0);
|
|
|
|
if (hnd == NULL) {
|
|
fprintf(stderr, "Error! Device not found!\n");
|
|
return 1;
|
|
}
|
|
|
|
parse_params(argc, argv);
|
|
|
|
/* åñëè óñïåøíî âûáðàëè ìîäóëü è óñòàíîâèëè ñ íèì ñâÿçü - ïðîäîëæàåì ðàáîòó */
|
|
|
|
err = f_setup_params(hnd);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
/********************************** Ðàáîòà ñ ìîäóëåì **************************/
|
|
|
|
/* Ðàçðåøàåì âñå êàíàëû íà âûâîä (â ýòîì ïðèìåðå ìû íå áóäåì
|
|
èñïîëüçîâàòü àñèíõðîííûé âûâîä), à êàêèå êàíàëû ðåàëüíî áóäóò
|
|
èñïîëüçîâàíû îïðåäåëÿåì êîãäà ïîäàåì äàííûå â L502_PrepareData */
|
|
err = X502_StreamsEnable(hnd, X502_STREAM_ALL_OUT);
|
|
if (err != X502_ERR_OK) {
|
|
fprintf(stderr, "Îøèáêà ðàçðåøåíèÿ ïîòîêîâ (%d): %s!", err,
|
|
X502_GetErrorString(err));
|
|
}
|
|
|
|
f = fopen(argv[argc - 1], "rb");
|
|
if (!f) {
|
|
fprintf(stderr, "Could not open file '%s' error %d\n", argv[argc - 1], errno);
|
|
show_help(argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
err = out_dac_from_file(hnd, f);
|
|
fclose(f);
|
|
|
|
/* çàêðûâàåì ñâÿçü ñ ìîäóëåì */
|
|
X502_Close(hnd);
|
|
/* îñâîáîæäàåì îïèñàòåëü */
|
|
X502_Free(hnd);
|
|
|
|
return err;
|
|
}
|
|
|
|
static struct timespec start_time;
|
|
static uint32_t* out_buf;
|
|
static int dac_size;
|
|
static double *dac_data[CH_ENABLED];
|
|
|
|
int send_data(t_x502_hnd hnd, uint32_t *send_ptr, uint32_t send_size) {
|
|
static int started = 0;
|
|
static uint32_t g_snd_cnt = 0;
|
|
struct timespec cur_time;
|
|
double spent_secs;
|
|
struct timespec spent_time;
|
|
|
|
while (send_size && !f_out) {
|
|
int32_t sent;
|
|
|
|
#ifdef _WIN32
|
|
/* ïðîâåðêà íàæàòèÿ êëàâèøè äëÿ âûõîäà */
|
|
if (_kbhit()) {
|
|
f_out = 1;
|
|
}
|
|
#endif
|
|
|
|
sent = X502_Send(hnd, send_ptr, send_size, SEND_TOUT);
|
|
if (sent < 0) {
|
|
fprintf(stderr, "Errror: X502_Send ret = %d\n", sent);
|
|
return sent;
|
|
}
|
|
if (f_out) {
|
|
return 0;
|
|
}
|
|
g_snd_cnt += sent;
|
|
send_size -= sent;
|
|
send_ptr += sent;
|
|
|
|
if (started == 0) {
|
|
int err;
|
|
|
|
started = 1;
|
|
err = X502_StreamsStart(hnd);
|
|
if (err) {
|
|
fprintf(stderr, "Error: X502_StreamsStart ret = %d\n", err);
|
|
return err;
|
|
}
|
|
}
|
|
}
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &cur_time);
|
|
|
|
timespec_diff(&cur_time, &start_time, &spent_time);
|
|
spent_secs = timespec_to_double(&spent_time);
|
|
|
|
if (spent_secs > 5) {
|
|
fprintf(stderr, "snd speed=%f wrds/sec\n", (g_snd_cnt) / (spent_secs));
|
|
g_snd_cnt = 0;
|
|
start_time = cur_time;
|
|
}
|
|
return send_size;
|
|
}
|
|
|
|
int send_dac_data(t_x502_hnd hnd) {
|
|
int err;
|
|
|
|
if (dac_size != DAC_BUF_SIZE) {
|
|
return 0;
|
|
}
|
|
|
|
#if 0
|
|
for (int i = 0; i < dac_size; i++){
|
|
fprintf(stderr, "[%d] %f; %f\n", i, dac_data[0][i], dac_data[1][i]);
|
|
}
|
|
#endif
|
|
// TODO: äëÿ LTA37 íàäî èñïîëüçîâàòü PrepareData2()
|
|
err = X502_PrepareData(hnd,
|
|
dac_data[0],
|
|
dac_data[1],
|
|
NULL,
|
|
dac_size, X502_DAC_FLAGS_VOLT | X502_DAC_FLAGS_CALIBR,
|
|
out_buf);
|
|
|
|
if (err) {
|
|
fprintf(stderr, "Error: X502_PrepareData ret = %d\n", err);
|
|
return err;
|
|
}
|
|
|
|
err = send_data(hnd, out_buf, dac_size * CH_ENABLED);
|
|
|
|
dac_size = 0;
|
|
|
|
return err;
|
|
}
|
|
|
|
int out_dac_from_file(t_x502_hnd hnd, FILE* f) {
|
|
int32_t err;
|
|
char *buf;
|
|
int items_read;
|
|
double dac_val;
|
|
char *read_start;
|
|
int cntr = 0;
|
|
int dac_ch = 0;
|
|
bool newline = false;
|
|
bool comment_start = false;
|
|
bool data_added = false;
|
|
char *last_endptr;
|
|
double last_dac_data[CH_ENABLED];
|
|
|
|
for (int ch = 0; ch < CH_ENABLED; ch++) {
|
|
dac_data[ch] = (double*)malloc(sizeof(double) * DAC_BUF_SIZE);
|
|
if (!dac_data[ch]) {
|
|
fprintf(stderr, "Out of memory\n");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
out_buf = (uint32_t*)malloc(sizeof(uint32_t) * DAC_BUF_SIZE * CH_ENABLED);
|
|
buf = (char*)malloc(BUF_SIZE);
|
|
if (!out_buf || !buf) {
|
|
fprintf(stderr, "Out of memory\n");
|
|
return 1;
|
|
}
|
|
|
|
read_start = buf;
|
|
last_endptr = &buf[BUF_SIZE];
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &start_time);
|
|
|
|
while (!f_out) {
|
|
size_t buf_ready = (read_start - buf);
|
|
|
|
#ifdef _WIN32
|
|
/* ïðîâåðêà íàæàòèÿ êëàâèøè äëÿ âûõîäà */
|
|
if (_kbhit()) {
|
|
f_out = 1;
|
|
}
|
|
#endif
|
|
|
|
if (feof(f) && cycle_mode) {
|
|
int delay_cntr = cycle_delay * dac_freq;
|
|
do {
|
|
for (; (dac_size != DAC_BUF_SIZE) && delay_cntr; dac_size++, delay_cntr--) {
|
|
for (int ch = 0; ch < CH_ENABLED; ch++) {
|
|
dac_data[ch][dac_size] = last_dac_data[ch];
|
|
}
|
|
}
|
|
if ((err = send_dac_data(hnd)) < 0) {
|
|
return err;
|
|
}
|
|
} while(delay_cntr);
|
|
}
|
|
|
|
if (feof(f)) {
|
|
if (cycle_mode) {
|
|
fseek(f, 0, SEEK_SET);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
items_read = fread(read_start, 1, BUF_SIZE - buf_ready, f);
|
|
dbg_printf("read_start=::::%.*s::::\n", (int)buf_ready, buf);
|
|
dbg_printf("read=%d '''''%.*s'''''\n", items_read, items_read, read_start);
|
|
|
|
for (char *ptr = buf, *endptr = buf; ; ptr = endptr) {
|
|
char *buf_end = &buf[buf_ready + items_read];
|
|
|
|
dac_val = strtod(ptr, &endptr);
|
|
if (endptr >= buf_end) {
|
|
memmove(buf, last_endptr, buf_end - last_endptr);
|
|
read_start = buf + (buf_end - last_endptr);
|
|
break;
|
|
} else
|
|
if (endptr == ptr) {
|
|
endptr++;
|
|
if (*ptr == '\n') {
|
|
newline = true;
|
|
comment_start = false;
|
|
}
|
|
if (*ptr == '#') {
|
|
comment_start = true;
|
|
}
|
|
} else {
|
|
last_endptr = endptr;
|
|
for (char *n_ptr = ptr; n_ptr < endptr; n_ptr++) {
|
|
if (*n_ptr == '\n') {
|
|
newline = true;
|
|
comment_start = false;
|
|
break;
|
|
}
|
|
}
|
|
if (comment_start) {
|
|
continue;
|
|
}
|
|
if (newline) {
|
|
dac_ch = 0;
|
|
}
|
|
|
|
if (dac_ch >= CH_ENABLED) {
|
|
fprintf(stderr, "dac_ch = %d >= %d (CH_ENABLED)\n", dac_ch, CH_ENABLED);
|
|
dac_ch %= CH_ENABLED;
|
|
}
|
|
|
|
if (newline && data_added) {
|
|
data_added = false;
|
|
dac_size++;
|
|
for (int ch = 0; ch < CH_ENABLED; ch++) {
|
|
dac_data[ch][dac_size] = dac_data[ch][dac_size - 1];
|
|
}
|
|
}
|
|
|
|
data_added = true;
|
|
newline = false;
|
|
|
|
dbg_printf("dac_val=%lf cntr=%d\n", dac_val, cntr);
|
|
|
|
if ((err = send_dac_data(hnd)) < 0) {
|
|
return err;
|
|
}
|
|
|
|
dac_data[dac_ch][dac_size] = dac_val;
|
|
last_dac_data[dac_ch] = dac_val;
|
|
dac_ch++;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|