Files
kamil_adc/main.c
2026-04-07 17:22:17 +03:00

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;
}