1636 lines
61 KiB
C
1636 lines
61 KiB
C
/* Данный пример представляет из себя консольную программу на языке C,
|
||
демонстрирующую работу с модулями E16, L502 и E502 на примере синхронного
|
||
ввода данных с АЦП и цифровых линий.
|
||
|
||
Перед сбором в примере идет поиск модулей, подключенных по интерфейсам PCI-Express и USB,
|
||
и предоставляется список для выбора модуля, с которым нужно работать.
|
||
Для подключения по Ethernet нужно указать IP-адреса интересующих модулей
|
||
в качестве аргументов командной строки при вызове примера, тогда эти адреса
|
||
будут добавлены в конец списка выбора модуля.
|
||
Например, если интересуют модули с адресами 192.168.1.5 и 192.168.1.6,
|
||
то пример можно вызвать:
|
||
x502_stream_read 192.168.1.5 E16:192.168.1.6
|
||
и две дополнительные строки с этими адресами появятся в списке выбора.
|
||
Для указания что ip адрес принадлежит модулю E16, адрес надо указать с префиксом, пример: E16:192.168.1.6
|
||
|
||
Настройки частот, количества принимаемых данных и т.д. задаются с помощью макросов в
|
||
начале программы.
|
||
Настройки логических каналов - с помощью таблиц f_channels/f_ch_modes/f_ch_ranges.
|
||
|
||
Пример выполняет прием блоков данных заданного размера.
|
||
Сбор идет до нажатия любой клавиши на Windows или CTRL+C на Linux.
|
||
|
||
Пример также показывает как выполнять обработку данных и определять начало кадра,
|
||
в случае если в X502_ProcessData() передается не целое число кадров.
|
||
|
||
Данный пример содержит проект для Visual Studio 2008, а также может быть собран
|
||
gcc в Linux или mingw в Windows через makefile или с помощью cmake (подробнее
|
||
в комментариях в соответствующих файлах).
|
||
|
||
Для того чтобы собрать проект в Visual Studio, измените путь к заголовочным файлам
|
||
(Проект (Project) -> Свойства (Properties) -> Свойства конфигурации (Configuration Properties)
|
||
-> С/С++ -> Общие (General) -> Дополнительные каталоги включения (Additional Include Directories))
|
||
на тот, где у вас лежат заголовочный файлы x502api.h, l502api.h и e502api.h и измените путь к библиотекам
|
||
(Проект (Project) -> Свойства (Properties) -> Свойства конфигурации (Configuration Properties) ->
|
||
Компановщик (Linker) -> Общие (General) -> Дополнительные катологи библиотек (Additional Library Directories)).
|
||
|
||
Внимание!!: Если Вы собираете проект под Visual Studio и взяли проект с сайта (а не из SDK),
|
||
то для корректного отображения русских букв в программе нужно изменить кодировку
|
||
или указать сохранение с сигнатурой кодировки для UTF-8:
|
||
выберите Файл (File) -> Дополнительные параметры сохранения (Advanced Save Options)...
|
||
и в поле Кодировка (Encoding) выберите Юникод (UTF8, с сигнатурой)/Unicode (UTF-8 with signature)
|
||
и сохраните изменения в файле.
|
||
|
||
*/
|
||
|
||
//#include "dislin.h" //graphics library
|
||
|
||
|
||
#include <time.h> //for namigs of saved files
|
||
|
||
#include <l502api.h>
|
||
#include "e502api.h"
|
||
//#include "dev_funcs.h"
|
||
|
||
#ifdef _WIN32
|
||
#include <locale.h>
|
||
#include <conio.h>
|
||
#else
|
||
#include <signal.h>
|
||
#include <unistd.h>
|
||
#include <string.h>
|
||
#endif
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
|
||
#include "l502_BF_enums.h"
|
||
#include "l502_fpga_regs.h"
|
||
|
||
|
||
typedef enum {
|
||
DUMP_TO_FILE,
|
||
FLUSH,
|
||
};
|
||
|
||
typedef enum {
|
||
unknown = 0x00,
|
||
ADC_data =0x01,
|
||
USR_data,
|
||
DIN_data,
|
||
FFT_val_re,
|
||
FFT_val_im,
|
||
FFT_val_f,
|
||
LFSM_val_ON,
|
||
LFSM_val_OFF,
|
||
LFSM_val_X,
|
||
USR_msg,
|
||
LFSM_started,
|
||
} BF_msg_parsed_type;
|
||
|
||
typedef struct BF_msg_parsed_typedef {
|
||
BF_msg_parsed_type type;
|
||
uint8_t chan;
|
||
uint8_t flags;
|
||
uint8_t raw_header;
|
||
uint32_t raw_data;
|
||
uint32_t raw_value;
|
||
int value_int;
|
||
double value;
|
||
};
|
||
|
||
typedef struct LFSM_typedef{ //Linear Frequency Sweep Modulation
|
||
int * X;
|
||
int * Y_on; //intensity while Mach-Zander modulator is "opened"
|
||
int * Y_off;//intensity while Mach-Zander modulator is "closed"
|
||
int ID;
|
||
uint8_t rcv_state;
|
||
int max_N; //max number of data points
|
||
int curr_I;
|
||
uint8_t description;
|
||
};
|
||
|
||
typedef struct FFT_res_typedef{
|
||
|
||
int * vals_Re;
|
||
int * vals_Im;
|
||
int * vals_F;
|
||
int values_N;
|
||
uint8_t rcv_state;
|
||
int max_N;
|
||
//int timestamp;
|
||
int ID;
|
||
uint8_t description;
|
||
int curr_I; //current index of value and corresponding frequency
|
||
} ;
|
||
|
||
const int FFT_length = 1000;
|
||
|
||
// количество используемых логических каналов //
|
||
#define ADC_LCH_CNT 4
|
||
|
||
// частота сбора АЦП в Гц//
|
||
#define ADC_FREQ 2000000
|
||
// частота кадров (на логический канал). При ADC_FREQ/ADC_LCH_CNT - межкадровой задержки нет //
|
||
#define ADC_FRAME_FREQ (ADC_FREQ/ADC_LCH_CNT)
|
||
// частота синхронного ввода в Гц//
|
||
#define DIN_FREQ 500000
|
||
|
||
|
||
#define TCP_CONNECTION_TOUT 5000
|
||
|
||
|
||
// сколько отсчетов считываем за блок //
|
||
#define READ_BLOCK_SIZE 4096*200
|
||
// таймаут на прием блока (мс) //
|
||
#define READ_TIMEOUT 2000
|
||
|
||
|
||
#define BF_CMD_USER_MULT 0x8001U
|
||
|
||
|
||
// номера используемых физических каналов //
|
||
static uint32_t f_channels[ADC_LCH_CNT] = {0, 0, 1, 0};
|
||
// режимы измерения для каналов //
|
||
static uint32_t f_ch_modes[ADC_LCH_CNT] = {X502_LCH_MODE_COMM, X502_LCH_MODE_COMM,X502_LCH_MODE_COMM,X502_LCH_MODE_COMM};
|
||
//static uint32_t f_ch_modes[ADC_LCH_CNT] = {X502_LCH_MODE_COMM};
|
||
//static uint32_t f_ch_modes[ADC_LCH_CNT] = {X502_LCH_MODE_COMM, X502_LCH_MODE_COMM,X502_LCH_MODE_COMM,X502_LCH_MODE_COMM,X502_LCH_MODE_COMM,X502_LCH_MODE_COMM,X502_LCH_MODE_COMM,X502_LCH_MODE_COMM,X502_LCH_MODE_COMM,X502_LCH_MODE_COMM};
|
||
//static uint32_t f_ch_modes[ADC_LCH_CNT] = {X502_LCH_MODE_COMM, X502_LCH_MODE_ZERO,X502_LCH_MODE_ZERO,X502_LCH_MODE_ZERO,X502_LCH_MODE_ZERO,X502_LCH_MODE_ZERO,X502_LCH_MODE_ZERO,X502_LCH_MODE_ZERO,X502_LCH_MODE_ZERO,X502_LCH_MODE_ZERO};
|
||
//X502_LCH_MODE_COMM0
|
||
//X502_LCH_MODE_DIFF
|
||
//X502_LCH_MODE_ZERO
|
||
|
||
// диапазоны измерения для каналов //
|
||
static uint32_t f_ch_ranges[ADC_LCH_CNT] = {X502_ADC_RANGE_5, X502_ADC_RANGE_5,X502_ADC_RANGE_5,X502_ADC_RANGE_5};
|
||
//static uint32_t f_ch_ranges[ADC_LCH_CNT] = {X502_ADC_RANGE_1};
|
||
//static uint32_t f_ch_ranges[ADC_LCH_CNT] = {X502_ADC_RANGE_1, X502_ADC_RANGE_1,X502_ADC_RANGE_1,X502_ADC_RANGE_1,X502_ADC_RANGE_1,X502_ADC_RANGE_1, X502_ADC_RANGE_1,X502_ADC_RANGE_1,X502_ADC_RANGE_1,X502_ADC_RANGE_1};
|
||
//static uint32_t f_ch_ranges[ADC_LCH_CNT] = {X502_ADC_RANGE_5, X502_ADC_RANGE_5,X502_ADC_RANGE_5,X502_ADC_RANGE_5,X502_ADC_RANGE_5,X502_ADC_RANGE_5, X502_ADC_RANGE_5,X502_ADC_RANGE_5,X502_ADC_RANGE_5,X502_ADC_RANGE_5};
|
||
//X502_ADC_RANGE_10 Диапазон +/-10V
|
||
//X502_ADC_RANGE_5 Диапазон +/-5V
|
||
//X502_ADC_RANGE_2 Диапазон +/-2V
|
||
//X502_ADC_RANGE_1 Диапазон +/-1V
|
||
//X502_ADC_RANGE_05 Диапазон +/-0.5V
|
||
//X502_ADC_RANGE_02 Диапазон +/-0.2V
|
||
|
||
|
||
|
||
#define SYNC_FREC_SOURCE X502_SYNC_DI_SYN1_RISE
|
||
#define SYNC_START_SOURCE X502_SYNC_DI_SYN2_RISE
|
||
|
||
|
||
|
||
//X502_SYNC_INTERNAL
|
||
//X502_SYNC_EXTERNAL_MASTER1
|
||
//X502_SYNC_DI_SYN1_RISE
|
||
//X502_SYNC_DI_SYN1_FALL
|
||
//X502_SYNC_DI_SYN2_RISE
|
||
//X502_SYNC_DI_SYN2_FALL
|
||
|
||
|
||
|
||
// признак необходимости завершить сбор данных //
|
||
static int f_out = 0;
|
||
|
||
#ifndef _WIN32
|
||
// Обработчик сигнала завершения для Linux //
|
||
static void f_abort_handler(int sig) {
|
||
f_out = 1;
|
||
}
|
||
#endif
|
||
|
||
char const *DEV_E502 = "E502";
|
||
char const *DEV_E16 = "E16";
|
||
|
||
typedef struct {
|
||
uint32_t ip_addr;
|
||
char const *devname;
|
||
} ip_dev_list_t;
|
||
|
||
|
||
volatile sig_atomic_t abort_crtl_C = 0;
|
||
|
||
void handle_sigint(int signal_stop){
|
||
(void)signal_stop;
|
||
abort_crtl_C = 1;
|
||
for (int i = 100; i ; --i){
|
||
printf("abort");
|
||
}
|
||
}
|
||
|
||
|
||
/* Функция находит все подключенные модули по интерфейсам PCI-Express и USB и
|
||
* сохраняет записи о этих устройствах в выделенный массив.
|
||
* Также создаются записи по переданным IP-адресам модулей и добавляются в конец
|
||
* массива.
|
||
* Указатель на выделенный массив, который должен быть потом очищен, сохраняется
|
||
* в pdevrec_list, а количество действительных элементов (память которых должна
|
||
* быть в дальнейшем освобождена с помощью X502_FreeDevRecordList()) возвращается
|
||
* как результат функции */
|
||
static uint32_t f_get_all_devrec(t_x502_devrec **pdevrec_list, ip_dev_list_t *ip_dev_list, unsigned ip_cnt) {
|
||
int32_t fnd_devcnt = 0;
|
||
uint32_t pci_devcnt = 0;
|
||
uint32_t usb_devcnt = 0;
|
||
uint32_t e16_usb_devcnt = 0;
|
||
|
||
t_x502_devrec *rec_list = NULL;
|
||
|
||
// получаем количество подключенных устройств по интерфейсам PCI и USB //
|
||
L502_GetDevRecordsList(NULL, 0, 0, &pci_devcnt);
|
||
E502_UsbGetDevRecordsList(NULL, 0, 0, &usb_devcnt);
|
||
// E16_UsbGetDevRecordsList(NULL, 0, 0, &e16_usb_devcnt);
|
||
|
||
if ((pci_devcnt+usb_devcnt + e16_usb_devcnt + ip_cnt) != 0) {
|
||
// выделяем память для массива для сохранения найденного количества записей //
|
||
rec_list = malloc((pci_devcnt + usb_devcnt +e16_usb_devcnt + ip_cnt) * sizeof(t_x502_devrec));
|
||
|
||
if (rec_list != NULL) {
|
||
unsigned i;
|
||
// получаем записи о модулях L502, но не больше pci_devcnt //
|
||
if (pci_devcnt!=0) {
|
||
int32_t res = L502_GetDevRecordsList(&rec_list[fnd_devcnt], pci_devcnt, 0, NULL);
|
||
if (res >= 0) {
|
||
fnd_devcnt += res;
|
||
}
|
||
}
|
||
// добавляем записи о модулях E502, подключенных по USB, в конец массива //
|
||
if (usb_devcnt!=0) {
|
||
int32_t res = E502_UsbGetDevRecordsList(&rec_list[fnd_devcnt], usb_devcnt, 0, NULL);
|
||
if (res >= 0) {
|
||
fnd_devcnt += res;
|
||
}
|
||
}
|
||
|
||
// добавляем записи о модулях E16, подключенных по USB, в конец массива //
|
||
// if (e16_usb_devcnt!=0) {
|
||
// int32_t res = E16_UsbGetDevRecordsList(&rec_list[fnd_devcnt], e16_usb_devcnt, 0, NULL);
|
||
// if (res >= 0) {
|
||
// fnd_devcnt += res;
|
||
// }
|
||
// }
|
||
|
||
// создаем записи для переданного массива ip-адресов //
|
||
|
||
}
|
||
}
|
||
|
||
if (fnd_devcnt != 0) {
|
||
// если создана хотя бы одна запись, то сохраняем указатель на выделенный массив //
|
||
*pdevrec_list = rec_list;
|
||
} else {
|
||
*pdevrec_list = NULL;
|
||
free(rec_list);
|
||
}
|
||
|
||
return fnd_devcnt;
|
||
}
|
||
|
||
|
||
static t_x502_hnd f_dev_select_open(int argc, char** argv) {
|
||
t_x502_hnd hnd = NULL;
|
||
uint32_t fnd_devcnt,i, dev_ind;
|
||
t_x502_devrec *devrec_list = NULL;
|
||
ip_dev_list_t *ip_dev_list = NULL;
|
||
uint32_t ip_cnt = 0;
|
||
|
||
// если есть аргументы командной строки, то предполагаем, что это могут быть
|
||
// ip-адреса интересующих устройств. //
|
||
if (argc > 1) {
|
||
ip_dev_list = malloc((argc - 1) * sizeof(ip_dev_list[0]));
|
||
if (ip_dev_list == NULL) {
|
||
fprintf(stderr, "Ошибка выделения памяти!\n");
|
||
} else {
|
||
for (i=1; (int)i < argc; i++) {
|
||
int a[4];
|
||
if (sscanf(argv[i], "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3])==4) {
|
||
ip_dev_list[ip_cnt].devname = DEV_E502;
|
||
ip_dev_list[ip_cnt++].ip_addr = ((a[0] & 0xFF) << 24) |
|
||
((a[1] & 0xFF) << 16) |
|
||
((a[2] & 0xFF) << 8) |
|
||
(a[3] & 0xFF);
|
||
} else
|
||
if (sscanf(argv[i], "E16:%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3])==4) {
|
||
ip_dev_list[ip_cnt].devname = DEV_E16;
|
||
ip_dev_list[ip_cnt++].ip_addr = ((a[0] & 0xFF) << 24) |
|
||
((a[1] & 0xFF) << 16) |
|
||
((a[2] & 0xFF) << 8) |
|
||
(a[3] & 0xFF);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// получаем список модулей для выбора //
|
||
fnd_devcnt = f_get_all_devrec(&devrec_list, ip_dev_list, ip_cnt);
|
||
|
||
if (fnd_devcnt == 0) {
|
||
printf("Не найдено ни одного модуля\n");
|
||
} else {
|
||
// выводим информацию по списку модулей //
|
||
printf("Доступны следующие модули:\n");
|
||
for (i=0; i < fnd_devcnt; i++) {
|
||
printf("Модуль № %d: %s, %-9s", i, devrec_list[i].devname,
|
||
devrec_list[i].iface == X502_IFACE_PCI ? "PCI/PCIe" :
|
||
devrec_list[i].iface == X502_IFACE_USB ? "USB" :
|
||
devrec_list[i].iface == X502_IFACE_ETH ? "Ethernet" : "?");
|
||
|
||
// при подключении по сети по IP-адресу серийный номер можно узнать
|
||
// только после открытия соединения. При этом поле location
|
||
// содержит строку с описанием адреса устройства //
|
||
if (devrec_list[i].iface != X502_IFACE_ETH) {
|
||
printf("Сер. номер: %s\n", devrec_list[i].serial);
|
||
} else {
|
||
printf("Адрес: %s\n", devrec_list[i].location);
|
||
}
|
||
}
|
||
|
||
// выбираем нужный по введенному номеру модуля по порядку с клавиатуры //
|
||
//printf("Введите номер модуля, с которым хотите работать (от 0 до %d)\n", fnd_devcnt-1);
|
||
//fflush(stdout);
|
||
//scanf("%d", &dev_ind);
|
||
dev_ind = 0;
|
||
|
||
if (dev_ind >= fnd_devcnt) {
|
||
printf("Неверно указан номер модуля...\n");
|
||
} else {
|
||
// если ввели номер правильно - создаем описатель //
|
||
hnd = X502_Create();
|
||
if (hnd==NULL) {
|
||
fprintf(stderr, "Ошибка создания описателя модуля!");
|
||
} else {
|
||
// устанавливаем связь с модулем по записи //
|
||
int32_t err = X502_OpenByDevRecord(hnd, &devrec_list[dev_ind]);
|
||
if (err != X502_ERR_OK) {
|
||
fprintf(stderr, "Ошибка установления связи с модулем: %s!", X502_GetErrorString(err));
|
||
X502_Free(hnd);
|
||
hnd = NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
// освобождение ресурсов действительных записей из списка //
|
||
X502_FreeDevRecordList(devrec_list, fnd_devcnt);
|
||
// очистка памяти самого массива //
|
||
free(devrec_list);
|
||
}
|
||
|
||
// освобождаем выделенный массив под IP-адреса (если был выделен) //
|
||
free(ip_dev_list);
|
||
|
||
return hnd;
|
||
}
|
||
|
||
|
||
// настройка параметров модуля //
|
||
int32_t f_setup_params(t_x502_hnd hnd) {
|
||
int32_t err = X502_ERR_OK, i;
|
||
|
||
// устанавливаем параметры логической таблицы АЦП //
|
||
err = X502_SetLChannelCount(hnd, ADC_LCH_CNT);
|
||
for (i=0; (i < ADC_LCH_CNT) && (err == X502_ERR_OK); i++)
|
||
err = X502_SetLChannel(hnd, i, f_channels[i], f_ch_modes[i], f_ch_ranges[i], 0);
|
||
|
||
// // устанавливаем частоты ввода для АЦП и цифровых входов //
|
||
// if (err == X502_ERR_OK) {
|
||
// double f_adc = ADC_FREQ, f_frame = ADC_FRAME_FREQ, f_din = DIN_FREQ;
|
||
// err = X502_SetAdcFreq(hnd, &f_adc, &f_frame);
|
||
// if (err == X502_ERR_OK)
|
||
// err = X502_SetDinFreq(hnd, &f_din);
|
||
// if (err == X502_ERR_OK) {
|
||
// // выводим реально установленные значения - те что вернули функции //
|
||
// printf("Установлены частоты:\n Частота сбора АЦП = %0.0f\n"
|
||
// " Частота на лог. канал = %0.0f\n Частота цифрового ввода = %0.0f\n",
|
||
// f_adc, f_frame, f_din);
|
||
// }
|
||
// }
|
||
|
||
|
||
|
||
//double f_din = DIN_FREQ;
|
||
//err = X502_SetDinFreq(hnd, &f_din);
|
||
//printf();
|
||
|
||
//set ADC sample frequency from internal generator with frequency 2 MHz
|
||
X502_SetRefFreq(hnd, X502_REF_FREQ_2000KHZ);
|
||
|
||
//=======================================================//
|
||
//for real work with Radar
|
||
//X502_SetSyncMode(hnd, X502_SYNC_DI_SYN1_FALL);
|
||
//X502_SetSyncStartMode(hnd, X502_SYNC_DI_SYN2_RISE); //start ADC sampling by external trigger
|
||
|
||
|
||
//=======================================================//
|
||
//for debug purposes:
|
||
// X502_SetRefFreq(hnd, X502_REF_FREQ_2000KHZ);
|
||
// X502_SetSyncMode(hnd, X502_SYNC_DI_SYN1_FALL);
|
||
//X502_SetSyncMode(hnd, X502_SYNC_INTERNAL);
|
||
//X502_SetSyncStartMode(hnd, X502_SYNC_INTERNAL); //start ADC samping after executing X502_StreamsStart()
|
||
// X502_SetSyncStartMode(hnd, X502_SYNC_DI_SYN2_RISE); //start ADC sampling by external trigger
|
||
|
||
X502_SetSyncMode(hnd, SYNC_FREC_SOURCE);
|
||
//X502_SetSyncMode(hnd, X502_SYNC_INTERNAL);
|
||
X502_SetSyncStartMode(hnd, SYNC_START_SOURCE);
|
||
|
||
//X502_SYNC_INTERNAL
|
||
//X502_SYNC_EXTERNAL_MASTER1
|
||
//X502_SYNC_DI_SYN1_RISE
|
||
//X502_SYNC_DI_SYN1_FALL
|
||
//X502_SYNC_DI_SYN2_RISE
|
||
//X502_SYNC_DI_SYN2_FALL
|
||
|
||
//set ADC sample frequency from internal generator with frequency 2 MHz
|
||
//X502_SetRefFreq(hnd, X502_REF_FREQ_1500KHZ);
|
||
//X502_REF_FREQ_1500KHZ
|
||
//X502_REF_FREQ_2000KHZ
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// записываем настройки в модуль //
|
||
if (err == X502_ERR_OK)
|
||
err = X502_Configure(hnd, 0);
|
||
|
||
// разрешаем синхронные потоки //
|
||
if (err == X502_ERR_OK) {
|
||
err = X502_StreamsEnable(hnd, X502_STREAM_ADC);
|
||
}
|
||
|
||
return err;
|
||
}
|
||
|
||
|
||
void uin32_t_to_bin(uint32_t val, char* string){
|
||
for (int i = 0; i < 8; ++i){
|
||
if (val & (0b1 << i)){
|
||
string[i] = '1';
|
||
}else{
|
||
string[i] = '0';
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
uint32_t BF_exec_cmd_simple(t_x502_hnd hnd, uint16_t cmd_code, uint32_t cmd_par, uint8_t verbosity_lvl){
|
||
|
||
uint32_t BF_cmd_receive_code = 0;
|
||
//uint16_t cmd_code = 0x8001; //read ADC data
|
||
//uint32_t cmd_par = 87;
|
||
const uint32_t snd_data[1] = {0,};
|
||
uint32_t snd_size = 0;
|
||
uint32_t rcv_data[100] = {0,};
|
||
uint32_t rcv_size = 100;
|
||
uint32_t tout = 1;
|
||
uint32_t recvd_size = 0;
|
||
//*/
|
||
if (verbosity_lvl == 2){
|
||
printf("\n\n");
|
||
|
||
printf("TX cmd_code: 0x%X\n", cmd_code);
|
||
printf("TX tout: %u\n", tout);
|
||
printf("TX par: %u\n", cmd_par);
|
||
printf("TX snd_data size: %u\n", snd_size);
|
||
for (int i = 0; i < snd_size; ++i){
|
||
printf(" 0x%0X,", snd_data[i]);
|
||
}
|
||
printf("\n");
|
||
printf("TX rcv_size: %u\n", rcv_size);
|
||
}
|
||
|
||
BF_cmd_receive_code = X502_BfExecCmd (hnd,
|
||
cmd_code,
|
||
cmd_par,
|
||
snd_data,
|
||
snd_size,
|
||
rcv_data,
|
||
rcv_size,
|
||
tout,
|
||
&recvd_size);
|
||
|
||
if (verbosity_lvl == 2){
|
||
|
||
printf("\n======================\n\n");
|
||
printf("RX received code dec: %u hex: 0x%3X, %d\n", BF_cmd_receive_code, BF_cmd_receive_code,BF_cmd_receive_code);
|
||
printf("RX recvd_size: %u\n", recvd_size);
|
||
printf("RX received_data:\n" );
|
||
for (int i = 0; i < recvd_size; ++i){
|
||
printf(" 0x%0X,", rcv_data[i]);
|
||
}
|
||
printf("\n\n\n\n");
|
||
}
|
||
|
||
|
||
|
||
if (verbosity_lvl == 1){
|
||
printf("\ncmd: 0x%0X, par: %d, rcv_code: %d, result[0]: %d (0x%0X) , result_L: %d\n", cmd_code, cmd_par, BF_cmd_receive_code, rcv_data[0],rcv_data[0], recvd_size);
|
||
}
|
||
return BF_cmd_receive_code;
|
||
}
|
||
|
||
uint32_t BF_exec_cmd_with_arr(t_x502_hnd hnd, uint16_t cmd_code, uint32_t cmd_par, uint32_t* snd_data, uint32_t snd_data_size, uint8_t verbosity_lvl){
|
||
|
||
uint32_t BF_cmd_receive_code = 0;
|
||
//uint16_t cmd_code = 0x8001; //read ADC data
|
||
//uint32_t cmd_par = 87;
|
||
//const uint32_t snd_data[1] = {0,};
|
||
//uint32_t snd_data_size = 0;
|
||
uint32_t rcv_data[100] = {0,};
|
||
uint32_t rcv_size = 100;
|
||
uint32_t tout = 1;
|
||
uint32_t recvd_size = 0;
|
||
//*/
|
||
if (verbosity_lvl == 2){
|
||
printf("\n\n");
|
||
printf("TX cmd_code: 0x%X\n", cmd_code);
|
||
printf("TX tout: %u\n", tout);
|
||
printf("TX par: %u\n", cmd_par);
|
||
printf("TX snd_data size: %u\n", snd_data_size);
|
||
for (int i = 0; i < snd_data_size; ++i){
|
||
printf(" 0x%0X,", snd_data[i]);
|
||
}
|
||
printf("\n");
|
||
printf("TX rcv_size: %u\n", rcv_size);
|
||
}
|
||
|
||
BF_cmd_receive_code = X502_BfExecCmd (hnd,
|
||
cmd_code,
|
||
cmd_par,
|
||
snd_data,
|
||
snd_data_size,
|
||
rcv_data,
|
||
rcv_size,
|
||
tout,
|
||
&recvd_size);
|
||
|
||
if (verbosity_lvl == 2){
|
||
|
||
printf("\n======================\n\n");
|
||
printf("RX received code dec: %u hex: 0x%3X, %d\n", BF_cmd_receive_code, BF_cmd_receive_code,BF_cmd_receive_code);
|
||
printf("RX recvd_size: %u\n", recvd_size);
|
||
printf("RX received_data:\n" );
|
||
for (int i = 0; i < recvd_size; ++i){
|
||
printf(" 0x%0X,", rcv_data[i]);
|
||
}
|
||
printf("\n\n\n\n");
|
||
}
|
||
|
||
|
||
|
||
if (verbosity_lvl == 1){
|
||
printf("\n");
|
||
printf("cmd: 0x%0X, par: %d, rcv_code: %d, result[0]: %d (0x%0X) , result_L: %d\n", cmd_code, cmd_par, BF_cmd_receive_code, rcv_data[0],rcv_data[0], recvd_size);
|
||
printf(" TX arr: ");
|
||
for (int i = 0; i < snd_data_size; ++i){
|
||
printf(" 0x%0X,", snd_data[i]);
|
||
}
|
||
printf("\n");
|
||
printf(" RX arr: ");
|
||
int values_in_line = 0;
|
||
|
||
for (int i = 0; i < recvd_size; ++i){
|
||
printf(" 0x%08X,", rcv_data[i]);
|
||
++values_in_line;
|
||
if (values_in_line == 10){
|
||
printf("\n");
|
||
values_in_line = 0;
|
||
}
|
||
}
|
||
printf("\n");
|
||
}
|
||
|
||
if (verbosity_lvl == 3){
|
||
printf("\n");
|
||
printf("cmd: 0x%0X, par: %d, rcv_code: %d, result[0]: %d (0x%0X) , result_L: %d\n", cmd_code, cmd_par, BF_cmd_receive_code, rcv_data[0],rcv_data[0], recvd_size);
|
||
printf(" TX arr: ");
|
||
for (int i = 0; i < snd_data_size; ++i){
|
||
printf(" 0x%0X,", snd_data[i]);
|
||
}
|
||
printf("\n");
|
||
printf(" RX arr: ");
|
||
int values_in_line = 0;
|
||
for (int i = 0; i < recvd_size; ++i){
|
||
char bin_str_val[9] = {0,};
|
||
uin32_t_to_bin(rcv_data[i], bin_str_val);
|
||
//printf(" 0x%0X,", rcv_data[i]);
|
||
printf(" 0b%s,", bin_str_val);
|
||
++values_in_line;
|
||
if (values_in_line == 10){
|
||
printf("\n");
|
||
values_in_line = 0;
|
||
}
|
||
}
|
||
printf("\n");
|
||
}
|
||
|
||
return BF_cmd_receive_code;
|
||
}
|
||
|
||
long int X502_Raw_User_Data_Parser(uint32_t *inp_buff, uint32_t inp_values_N,
|
||
double *adc_data, uint32_t *adc_chans_N, uint32_t *adc_readouts_N,
|
||
struct LFSM_typedef ** LFSM_data, struct LFSM_typedef ** LFSM_data_done,
|
||
struct FFT_res_typedef ** FFT_data, struct FFT_res_typedef ** FFT_data_done){
|
||
long int return_res = 0;
|
||
//printf("inp_values_N: %d, adc_chans_N: %d, adc_readouts_N: %d, user_data_chans_N: %d, user_data_readouts_N: %d\n", inp_values_N, adc_chans_N, adc_readouts_N, user_data_chans_N, user_data_readouts_N);
|
||
|
||
/*
|
||
for (int I = 0; I < adc_readouts_N; ++I){
|
||
adc_data[I] = 0.0;
|
||
}
|
||
for (int I = 0; I < user_data_readouts_N; ++I){
|
||
user_data[I] = 0.0;
|
||
}
|
||
*/
|
||
|
||
/*
|
||
(*(*(*(*(*(*(*(*FFT_data))))))))-> values_N = 0;
|
||
(*FFT_data)-> ID = 0;
|
||
(*FFT_data)-> description = 0;
|
||
(*FFT_data)-> curr_I = 0; //current index of value and corresponding frequency
|
||
|
||
for (int I = 0; I < adc_readouts_N; ++I){
|
||
(*FFT_data)->vals_Re [I] = 0;
|
||
(*FFT_data)-> vals_Im [I] = 0;
|
||
(*FFT_data)-> vals_F [I] = 0;
|
||
}
|
||
|
||
*/
|
||
|
||
|
||
struct BF_msg_parsed_typedef BF_msg;
|
||
for (uint32_t inp_buff_I = 0; inp_buff_I < inp_values_N; ++inp_buff_I){
|
||
|
||
BF_msg.raw_data = inp_buff[inp_buff_I];
|
||
BF_msg.raw_header = (uint8_t) (BF_msg.raw_data >> 24);
|
||
|
||
BF_msg.flags = 0;
|
||
BF_msg.type = 0;
|
||
BF_msg.chan = 0;
|
||
//BF_msg.raw_data = 0;
|
||
BF_msg.raw_value = BF_msg.raw_data & 0xFFFFFF;
|
||
BF_msg.value_int = 0;
|
||
BF_msg.value = 0;
|
||
|
||
if (BF_msg.raw_header & 0b10000000){ // ADC data
|
||
BF_msg.type = ADC_data;
|
||
BF_msg.chan = BF_msg.raw_header & 0b00001111;
|
||
BF_msg.flags = (BF_msg.raw_header >> 4);
|
||
BF_msg.value_int = BF_msg.raw_value & 0x7FFFFF;
|
||
if (BF_msg.raw_value & 0x800000){ // if first bit is nonzero -- it is negative value
|
||
BF_msg.value_int *= -1;
|
||
}
|
||
BF_msg.value = 0.0;// TODO conversion from int to double with respect to ADC channel voltage range
|
||
|
||
|
||
}else if (BF_msg.raw_header & 0b01000000){ //user data (FFT,)
|
||
if (BF_msg.raw_header & 0x0F == FFT_val_re){
|
||
BF_msg.type = FFT_val_re;
|
||
}else if (BF_msg.raw_header & 0x0F == FFT_val_im){
|
||
BF_msg.type = FFT_val_im;
|
||
}else if (BF_msg.raw_header & 0x0F == FFT_val_f){
|
||
BF_msg.type = FFT_val_f;
|
||
}else{
|
||
BF_msg.type = USR_data;
|
||
}
|
||
BF_msg.chan = 0;
|
||
//BF_msg.chan == BF_msg.raw_header & 0b00111111;
|
||
BF_msg.value_int = BF_msg.raw_value & 0x7FFFFF;
|
||
if (BF_msg.raw_value & 0x800000){ // if first bit is nonzero -- it is negative value
|
||
BF_msg.value_int *= -1;
|
||
}
|
||
if (! (((*FFT_data)-> rcv_state) & (0b1 << 7 ))){
|
||
if (BF_msg.type == FFT_val_re){
|
||
(*FFT_data)->rcv_state |= 0b1 << 0;
|
||
(*FFT_data)-> vals_Re[(*FFT_data)->curr_I] = BF_msg.value_int;
|
||
}else if (BF_msg.type == FFT_val_im){
|
||
(*FFT_data)->rcv_state |= 0b1 << 1;
|
||
(*FFT_data)-> vals_Im[(*FFT_data)->curr_I] = BF_msg.value_int;
|
||
}else if (BF_msg.type == FFT_val_f){
|
||
(*FFT_data)->rcv_state |= 0b1 << 2;
|
||
(*FFT_data)-> vals_F[(*FFT_data)->curr_I] = BF_msg.value_int;
|
||
}
|
||
if ((*FFT_data)-> rcv_state == 0b111){
|
||
(*FFT_data)-> rcv_state = 0;
|
||
++(*FFT_data)->curr_I;
|
||
if ((*FFT_data)->curr_I >= (*FFT_data)->max_N){
|
||
(*FFT_data)-> rcv_state |= 0b1 << 7;
|
||
printf("received more FFT values than allowed. <========================== ERROR\n");
|
||
|
||
}
|
||
}
|
||
}
|
||
}else if (BF_msg.raw_header & 0b01100000){ //user data LFSM)
|
||
if (BF_msg.raw_header & 0x0F == LFSM_val_ON){
|
||
BF_msg.type = LFSM_val_ON;
|
||
}else if (BF_msg.raw_header & 0x0F == LFSM_val_OFF){
|
||
BF_msg.type = LFSM_val_OFF;
|
||
}else if (BF_msg.raw_header & 0x0F == LFSM_val_X){
|
||
BF_msg.type = LFSM_val_X;
|
||
}else{
|
||
BF_msg.type = USR_data;
|
||
}
|
||
BF_msg.chan = 0;
|
||
//BF_msg.chan == BF_msg.raw_header & 0b00111111;
|
||
BF_msg.value_int = BF_msg.raw_value & 0x7FFFFF;
|
||
if (BF_msg.raw_value & 0x800000){ // if first bit is nonzero -- it is negative value
|
||
BF_msg.value_int *= -1;
|
||
}
|
||
if (! (((*LFSM_data) -> rcv_state) & (0b1 << 7 ))){
|
||
if (BF_msg.type == LFSM_val_ON){
|
||
(*LFSM_data) ->rcv_state |= 0b1 << 0;
|
||
(*LFSM_data) -> Y_on[(*LFSM_data) ->curr_I] = BF_msg.value_int;
|
||
}else if (BF_msg.type == LFSM_val_OFF){
|
||
(*LFSM_data) ->rcv_state |= 0b1 << 1;
|
||
(*LFSM_data) -> Y_off[(*LFSM_data) ->curr_I] = BF_msg.value_int;
|
||
}else if (BF_msg.type == LFSM_val_X){
|
||
(*LFSM_data) ->rcv_state |= 0b1 << 2;
|
||
(*LFSM_data) -> X[(*LFSM_data) ->curr_I] = BF_msg.value_int;
|
||
}
|
||
if ((*LFSM_data) -> rcv_state == 0b011){
|
||
(*LFSM_data) -> rcv_state = 0;
|
||
++(*LFSM_data) ->curr_I;
|
||
if ((*LFSM_data) ->curr_I >= (*LFSM_data) ->max_N){
|
||
(*LFSM_data) -> rcv_state |= 0b1 << 7;
|
||
printf("received more LFSM values than allowed. <========================== ERROR\n");
|
||
}
|
||
}
|
||
}
|
||
|
||
}else if (BF_msg.raw_header & 0b01100000 == 0b01100000){ //user message
|
||
BF_msg.type = USR_msg;
|
||
BF_msg.chan = BF_msg.raw_header & 0b00011111;
|
||
BF_msg.value_int = BF_msg.raw_value & 0x7FFFFF;
|
||
if (BF_msg.raw_value & 0x800000){ // if first bit is nonzero -- it is negative value
|
||
BF_msg.value_int *= -1;
|
||
}
|
||
printf("Received USR msg: 0x%06H \n", BF_msg.raw_value);
|
||
|
||
//}else if (raw_header & 0b01100000 == 0b01100000){ //
|
||
}else if (BF_msg.raw_header & 0b01101010 == 0b01101010){ //new Frequency Sweep Started. So save old (*FFT_data)to FFT_data_done and start working with new FFT_data
|
||
//FFT
|
||
printf("Received: new LFSM started. msg payload: 0x%06H \n", BF_msg.raw_value);
|
||
(*FFT_data)-> rcv_state = 0xFF; // data filled
|
||
int FFT_last_ID = (*FFT_data)-> ID;
|
||
int FFT_points_max_N = (*FFT_data)-> max_N;
|
||
struct FFT_res_typedef ** FFT_tmp = *FFT_data_done;
|
||
*FFT_data_done = *FFT_data;
|
||
*FFT_data = *FFT_tmp;
|
||
|
||
|
||
//(*FFT_data)-> values_N = 0;
|
||
(*FFT_data)-> rcv_state = 0;
|
||
(*FFT_data)-> ID = FFT_last_ID + 1;
|
||
(*FFT_data)-> max_N = FFT_points_max_N;
|
||
(*FFT_data)-> description = 0;
|
||
(*FFT_data)-> curr_I = 0; //current index of value and corresponding frequency
|
||
|
||
for (int I = 0; I < (*FFT_data)-> max_N; ++I){
|
||
(*FFT_data)->vals_Re [I] = 0;
|
||
(*FFT_data)-> vals_Im [I] = 0;
|
||
(*FFT_data)-> vals_F [I] = 0;
|
||
}
|
||
free(FFT_tmp);
|
||
free(FFT_last_ID);
|
||
free(FFT_points_max_N);
|
||
|
||
//LFSM
|
||
(*LFSM_data) -> rcv_state = 0xFF; // data filled
|
||
int LFSM_last_ID = (*LFSM_data) -> ID;
|
||
int LFSM_points_max_N = (*LFSM_data) -> max_N;
|
||
struct LFSM_typedef ** LFSM_tmp = *LFSM_data_done;
|
||
*LFSM_data_done = *LFSM_data;
|
||
*LFSM_data = *LFSM_tmp;
|
||
|
||
|
||
//(*LFSM_data) -> values_N = 0;
|
||
(*LFSM_data) -> rcv_state = 0;
|
||
(*LFSM_data) -> ID = LFSM_last_ID + 1;
|
||
(*LFSM_data) -> max_N = LFSM_points_max_N;
|
||
(*LFSM_data) -> description = 0;
|
||
(*LFSM_data) -> curr_I = 0; //current index of value and corresponding frequency
|
||
for (int I = 0; I < (*LFSM_data) -> max_N; ++I){
|
||
(*LFSM_data) -> X [I] = 0;
|
||
(*LFSM_data) -> Y_on [I] = 0;
|
||
(*LFSM_data) -> Y_off [I] = 0;
|
||
}
|
||
free(LFSM_tmp);
|
||
free(LFSM_last_ID);
|
||
free(LFSM_points_max_N);
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
}else{
|
||
BF_msg.type = unknown;
|
||
BF_msg.chan = 0;
|
||
BF_msg.value_int = BF_msg.raw_value & 0x7FFFFF;
|
||
if (BF_msg.raw_value & 0x800000){ // if first bit is nonzero -- it is negative value
|
||
BF_msg.value_int *= -1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
uint32_t X502_FlushRcv_buff(t_x502_hnd hnd){
|
||
uint32_t ready;
|
||
X502_GetRecvReadyCount(hnd, &ready);
|
||
if (ready > 0) {
|
||
uint32_t *tmp = malloc(ready * sizeof(uint32_t));
|
||
X502_Recv(hnd, tmp, ready, 0); // вычитываем и отбрасываем
|
||
free(tmp);
|
||
}
|
||
return ready;
|
||
}
|
||
|
||
|
||
void receive_to_file(t_x502_hnd hnd, char* logfilename, uint32_t* inp_buff, uint32_t max_total_words){
|
||
FILE* logfile_ptr = fopen(logfilename, "a");
|
||
uint32_t recv_Err_code = X502_Recv(hnd, inp_buff, max_total_words, 10000);
|
||
if (recv_Err_code > 0){
|
||
uint32_t received_words = recv_Err_code;
|
||
for (uint32_t word_I = 0; word_I < received_words; word_I ++){
|
||
//printf("%06d 0x%08X\n", word_I, inp_buff[word_I]);
|
||
fprintf(logfile_ptr, "0x%08X \n", inp_buff[word_I]);
|
||
}
|
||
printf("received %ld words\n", received_words);
|
||
}else{
|
||
printf("receive error: %d\n======================\n", recv_Err_code);
|
||
}
|
||
fclose(logfile_ptr);
|
||
}
|
||
|
||
void receive_data(t_x502_hnd hnd, char* logfilename, uint32_t* inp_buff, int data_receive_trys_counter, uint32_t max_total_words, uint8_t mode){
|
||
//int data_receive_trys_counter = 100;
|
||
//uint32_t max_total_words = 10000;
|
||
uint32_t ready_cnt_Err = 0;
|
||
uint32_t recv_Err_code = 0;
|
||
|
||
int ready_cnt = 0;
|
||
int ready_cnt_copy = 0;
|
||
int values_in_line = 0;
|
||
|
||
FILE *logfile_ptr;
|
||
|
||
logfile_ptr = fopen(logfilename, "a");
|
||
|
||
//while((--data_receive_trys_counter)&& (max_total_words)){
|
||
|
||
//ready_cnt_Err = X502_GetRecvReadyCount(hnd, &ready_cnt);
|
||
recv_Err_code = X502_Recv(hnd, inp_buff, max_total_words, data_receive_trys_counter);
|
||
//printf("\n\nget counters of calls of SPORT_RX, SPORT_TX, HDMA_RX, HDMA_TX\n");
|
||
//BF_exec_cmd_with_arr(hnd, 0x8005U, 100, NULL, 0, 1);
|
||
//printf("\n\request TX_buff_I_shadow value (last size of TX_buff transferred to pc )\n");
|
||
//BF_exec_cmd_simple(hnd, 0x8009, 10, 1);
|
||
if (mode == DUMP_TO_FILE){
|
||
if (ready_cnt){
|
||
printf("Ready count: %d, Err: %d \n", ready_cnt, ready_cnt_Err);
|
||
for (int i = 0; i < ready_cnt; ++i){
|
||
//printf("\nabort value: %d\n", abort_crtl_C);
|
||
if (abort_crtl_C){
|
||
break;
|
||
}
|
||
--max_total_words;
|
||
if (max_total_words == 0){
|
||
break;
|
||
}
|
||
char bin_str_val[9] = {0,};
|
||
uin32_t_to_bin(inp_buff[i], bin_str_val);
|
||
printf(" 0x%08X,", inp_buff[i]);
|
||
fprintf(logfile_ptr, "0x%08X \n", inp_buff[i]);
|
||
//printf(" 0b%s,", bin_str_val);
|
||
++values_in_line;
|
||
if (values_in_line == 10){
|
||
printf("\n");
|
||
values_in_line = 0;
|
||
}
|
||
}
|
||
|
||
/*
|
||
uint32_t process_data_Err = 0;
|
||
uint32_t adc_data_size = ready_cnt;
|
||
X502_Raw_User_Data_Parser(inp_buff, inp_values_N,
|
||
adc_data, adc_chans_N, adc_readouts_N,
|
||
&LFSM_res_tmp, &LFSM_res,
|
||
&FFT_res_tmp, &FFT_res);
|
||
//process_data_Err = X502_ProcessData(hnd, inp_buff, ready_cnt, X502_PROC_FLAGS_VOLT, adc_data, &adc_data_size, NULL, NULL);
|
||
uint64_t data_sum = 0;
|
||
for (int i = 0; i < ready_cnt; ++i){
|
||
data_sum += inp_buff[i];
|
||
if (i % 1000 == 1){
|
||
//printf(" %e\n", adc_data[i]);
|
||
}
|
||
}
|
||
*/
|
||
}
|
||
}else if (mode == FLUSH){
|
||
;
|
||
}
|
||
//printf("try: %04d, words ready: %06d, receive_error_code: %05d, data_sum: %d \n", data_receive_trys_counter, ready_cnt, recv_Err_code, data_sum);
|
||
//}
|
||
fclose(logfile_ptr);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
int main(int argc, char** argv) {
|
||
signal(SIGINT, handle_sigint);
|
||
int32_t err = X502_ERR_OK;
|
||
uint32_t ver;
|
||
t_x502_hnd hnd = NULL;
|
||
#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
|
||
// для вывода русских букв в консоль для ОС Windows в CP1251 без перевода в OEM //
|
||
setlocale(LC_CTYPE, "");
|
||
#endif
|
||
// получаем версию библиотеки //
|
||
ver = X502_GetLibraryVersion();
|
||
printf("Версия библиотеки: %d.%d.%d\n", (ver >> 24)&0xFF, (ver>>16)&0xFF, (ver>>8)&0xFF);
|
||
|
||
//*
|
||
uint32_t inp_buff[2] = {0,};
|
||
double adc_data[1] = {0,};
|
||
double user_data[1] = {0,};
|
||
uint32_t inp_values_N = 0;
|
||
uint32_t adc_chans_N = 1;
|
||
uint32_t adc_readouts_N= 2;
|
||
uint32_t user_data_chans_N = 3;
|
||
uint32_t user_data_readouts_N = 4;
|
||
//uint32_t FFT_data_readouts_N = 5;
|
||
|
||
|
||
|
||
struct FFT_res_typedef FFT_res_tmp;
|
||
FFT_res_tmp.max_N = 1000;
|
||
FFT_res_tmp.vals_Re = malloc(FFT_res_tmp.max_N * sizeof(int));
|
||
FFT_res_tmp.vals_Im = malloc(FFT_res_tmp.max_N *sizeof(int));
|
||
FFT_res_tmp.vals_F = malloc(FFT_res_tmp.max_N * sizeof(int));
|
||
FFT_res_tmp.curr_I = 0;
|
||
FFT_res_tmp.description = 0;
|
||
FFT_res_tmp.rcv_state = 0;
|
||
FFT_res_tmp.ID = 0;
|
||
|
||
struct FFT_res_typedef FFT_res;
|
||
FFT_res.ID = 0;
|
||
|
||
|
||
struct LFSM_typedef LFSM_res_tmp;
|
||
LFSM_res_tmp.max_N = 1000;
|
||
LFSM_res_tmp.X = malloc(LFSM_res_tmp.max_N * sizeof(int));
|
||
LFSM_res_tmp.Y_on = malloc(LFSM_res_tmp.max_N *sizeof(int));
|
||
LFSM_res_tmp.Y_off = malloc(LFSM_res_tmp.max_N * sizeof(int));
|
||
LFSM_res_tmp.curr_I = 0;
|
||
LFSM_res_tmp.description = 0;
|
||
LFSM_res_tmp.rcv_state = 0;
|
||
LFSM_res_tmp.ID = 0;
|
||
|
||
struct LFSM_typedef LFSM_res;
|
||
LFSM_res.ID = 0;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/*
|
||
X502_Raw_User_Data_Parser(inp_buff, inp_values_N,
|
||
adc_data, adc_chans_N, adc_readouts_N,
|
||
&LFSM_res_tmp, &LFSM_res,
|
||
&FFT_res_tmp, &FFT_res);
|
||
*/
|
||
//*/
|
||
|
||
/*
|
||
X502_Raw_User_Data_Parser(inp_buff, inp_values_N,
|
||
adc_data, adc_chans_N, adc_readouts_N,
|
||
user_data, user_data_chans_N, user_data_readouts_N);
|
||
*/
|
||
|
||
|
||
////******* Получение списка устройств и выбор, с каким будем работать *****************//
|
||
hnd = f_dev_select_open(argc, argv);
|
||
|
||
////******************************* Работа с модулем *************************//
|
||
// если успешно выбрали модуль и установили с ним связь - продолжаем работу //
|
||
if (hnd != NULL) {
|
||
// получаем информацию //
|
||
t_x502_info info;
|
||
err = X502_GetDevInfo(hnd, &info);
|
||
if (err != X502_ERR_OK) {
|
||
fprintf(stderr, "Ошибка получения серийного информации о модуле: %s!", X502_GetErrorString(err));
|
||
} else {
|
||
// выводим полученную информацию //
|
||
printf("Установлена связь со следующим модулем:\n");
|
||
printf(" Серийный номер : %s\n", info.serial);
|
||
printf(" Наличие ЦАП : %s\n", info.devflags & X502_DEVFLAGS_DAC_PRESENT ? "Да" : "Нет");
|
||
printf(" Наличие BlackFin : %s\n", info.devflags & X502_DEVFLAGS_BF_PRESENT ? "Да" : "Нет");
|
||
printf(" Наличие гальваноразвязки: %s\n", info.devflags & X502_DEVFLAGS_GAL_PRESENT ? "Да" : "Нет");
|
||
printf(" Индустриальное исп. : %s\n", info.devflags & X502_DEVFLAGS_INDUSTRIAL ? "Да" : "Нет");
|
||
printf(" Наличие интерф. PCI/PCIe: %s\n", info.devflags & X502_DEVFLAGS_IFACE_SUPPORT_PCI ? "Да" : "Нет");
|
||
printf(" Наличие интерф. USB : %s\n", info.devflags & X502_DEVFLAGS_IFACE_SUPPORT_USB ? "Да" : "Нет");
|
||
printf(" Наличие интерф. Ethernet: %s\n", info.devflags & X502_DEVFLAGS_IFACE_SUPPORT_ETH ? "Да" : "Нет");
|
||
printf(" Версия ПЛИС : %d.%d\n", (info.fpga_ver >> 8) & 0xFF, info.fpga_ver & 0xFF);
|
||
printf(" Версия PLDA : %d\n", info.plda_ver);
|
||
if (info.mcu_firmware_ver != 0) {
|
||
printf(" Версия прошивки ARM : %d.%d.%d.%d\n",
|
||
(info.mcu_firmware_ver >> 24) & 0xFF,
|
||
(info.mcu_firmware_ver >> 16) & 0xFF,
|
||
(info.mcu_firmware_ver >> 8) & 0xFF,
|
||
info.mcu_firmware_ver & 0xFF);
|
||
}
|
||
}
|
||
|
||
|
||
X502_StreamsStop(hnd); //stop all streams. We need it because we can connect to module that is already sampling. And sampling blocks any setup trials.
|
||
|
||
if (err == X502_ERR_OK) {
|
||
// настраиваем параметры модуля //
|
||
err = f_setup_params(hnd);
|
||
if (err != X502_ERR_OK)
|
||
fprintf(stderr, "Ошибка настройки модуля: %s!", X502_GetErrorString(err));
|
||
}
|
||
|
||
char* BF_firmware_filename = "l502-BFfirmware0.ldr";
|
||
|
||
if (1){
|
||
|
||
printf("loading Blackfin firmware file: %s\n", BF_firmware_filename);
|
||
|
||
uint32_t bf_firmware_load_state = X502_BfLoadFirmware(hnd, BF_firmware_filename); //load firmware from l502-BFfirmware0.ldr file to BlackFin
|
||
printf("load state: %d \n", bf_firmware_load_state);
|
||
|
||
}else{
|
||
printf("No BF firmware loaded\n");
|
||
}
|
||
printf("setup module again");
|
||
if (err == X502_ERR_OK) {
|
||
// настраиваем параметры модуля //
|
||
err = f_setup_params(hnd);
|
||
if (err != X502_ERR_OK)
|
||
fprintf(stderr, "Ошибка настройки модуля: %s!", X502_GetErrorString(err));
|
||
}
|
||
|
||
|
||
uint32_t BF_cmd_receive_code = 0;
|
||
|
||
|
||
/*//working executing remote cmd
|
||
uint16_t cmd_code = 3;
|
||
uint32_t par = 87;
|
||
const uint32_t snd_data[] = {1,1,2,2,3,4,5,56,67,23,1};
|
||
uint32_t snd_size = 11;
|
||
uint32_t rcv_data[13] = {0,};
|
||
uint32_t rcv_size = 13;
|
||
uint32_t tout = 1;
|
||
uint32_t recvd_size = 0;
|
||
*/
|
||
printf("\n\n\n");
|
||
|
||
//setup ADC:
|
||
|
||
//t_x502_hnd hnd, uint16_t cmd_code, uint32_t cmd_arg, uint8_t verbosity_lvl
|
||
//BF_exec_cmd_simple(hnd, L502_BF_CMD_CODE_GET_PARAM, 87, 2);
|
||
//BF_exec_cmd_simple(hnd, L502_BF_CMD_CODE_GET_PARAM, 87, 1);
|
||
//BF_exec_cmd_simple(hnd, L502_BF_CMD_CODE_GET_PARAM, 87, 0);
|
||
|
||
|
||
//BF_exec_cmd_simple(hnd, L502_BF_USR_CMD_CODE_ECHO, 87, 1);
|
||
//BF_exec_cmd_simple(hnd, L502_BF_USR_CMD_CODE_DATA_ECHO, 87, 1);
|
||
|
||
//BF_exec_cmd_with_arr(t_x502_hnd hnd, uint16_t cmd_code, uint32_t cmd_par, uint32_t* snd_data, uint32_t snd_data_size, uint8_t verbosity_lvl);
|
||
|
||
//uint32_t tx_data[] = {0,1,2,3,4,53,4,2,2,1,0};
|
||
//uint32_t tx_data_size = 11;
|
||
|
||
//BF_exec_cmd_with_arr(hnd, L502_BF_USR_CMD_CODE_DATA_ECHO, 328, tx_data, tx_data_size, 2);
|
||
//BF_exec_cmd_with_arr(hnd, L502_BF_USR_CMD_CODE_DATA_ECHO, 328, tx_data, tx_data_size, 1);
|
||
|
||
//setup ADC:
|
||
uint32_t tx_data[] = {0,1,2,3,4,53,4,2,2,1,0};
|
||
|
||
//set ADC Установка значения опорной частоты
|
||
uint32_t tx_data_size = 1;
|
||
tx_data[0] = 2000000; //valid values: 2000000, 1500000 Hz
|
||
//printf("\n");
|
||
|
||
//BF_exec_cmd_with_arr(hnd, L502_BF_CMD_CODE_SET_PARAM, L502_BF_PARAM_REF_FREQ_SRC, tx_data, tx_data_size, 2);
|
||
|
||
//printf("run tests\n");
|
||
//BF_exec_cmd_simple(hnd, 0x8010, 17, 1); //test SPORT0
|
||
|
||
|
||
//BF_exec_cmd_simple(hnd, 0x8003U, 0, 1);
|
||
//printf("setup ADC\n");
|
||
//BF_exec_cmd_with_arr(hnd, 0x8003U, 0, NULL, 0, 1); //setup ADC. Values in array are configuring functions return codes
|
||
|
||
//some delay to allow ADC to acquire some data
|
||
|
||
//printf("L502_REGS_IOHARD_OUTSWAP_BFCTL reg:");
|
||
//BF_exec_cmd_simple(hnd, 0x8006, L502_REGS_IOHARD_OUTSWAP_BFCTL, 1); //reaf fpga reg
|
||
|
||
uint32_t streams_enable_Err = 0;
|
||
streams_enable_Err = X502_StreamsEnable(hnd, X502_STREAM_ADC | X502_STREAM_DIN );
|
||
printf("Streams enable err: %d \n", streams_enable_Err);
|
||
uint32_t streams_start_Err = 0;
|
||
streams_start_Err = X502_StreamsStart(hnd);
|
||
printf("Streams start err: %d \n", streams_start_Err);
|
||
|
||
|
||
time_t seconds;
|
||
time(&seconds);
|
||
char logfilename[] = " ";
|
||
sprintf(&logfilename, "data/received_data_%ld.csv", seconds);
|
||
//logfile_ptr = fopen(logfilename, "w");
|
||
FILE *logfile_ptr;
|
||
logfile_ptr = fopen(logfilename, "a");
|
||
|
||
fprintf(logfile_ptr, "sync_frec_source: %d \nsync_start_source: %d \n", SYNC_FREC_SOURCE, SYNC_START_SOURCE);
|
||
|
||
for (int chan_I = 0; chan_I < ADC_LCH_CNT; chan_I++){
|
||
fprintf(logfile_ptr, "chan: %d, mode: %d, range: %d \n", chan_I, f_ch_modes[chan_I], f_ch_ranges[chan_I]);
|
||
}
|
||
fclose(logfile_ptr);
|
||
|
||
|
||
printf("dumping to file: %s\n", logfilename);
|
||
|
||
printf("\n");
|
||
//printf("start streams sampling\n");
|
||
//BF_exec_cmd_with_arr(hnd, 0x8004U, 0, NULL, 0, 1); //setup and start streams
|
||
|
||
|
||
|
||
uint32_t waiting_cnt = 1;
|
||
waiting_cnt = 100000;
|
||
printf("\nwaiting %d ...", waiting_cnt);
|
||
while(--waiting_cnt){;}
|
||
//for(uint32_t timeout = 100000000; timeout; --timeout){;}
|
||
printf("done\n");
|
||
|
||
printf("\n\nget counters of calls of SPORT_RX, SPORT_TX, HDMA_RX, HDMA_TX\n");
|
||
BF_exec_cmd_with_arr(hnd, 0x8005U, 100, NULL, 0, 1);
|
||
|
||
|
||
// printf("\n\nget a some data made by sport isr handler\n");
|
||
// BF_exec_cmd_with_arr(hnd, 0x8006U, 100, NULL, 0, 1);
|
||
//BF_exec_cmd_with_arr(hnd, 0x8006U, 100, NULL, 0, 3);
|
||
|
||
|
||
uint32_t *inp_buff = malloc(1024*100*1024*2*4);
|
||
double *adc_data = malloc(1024*1024*sizeof(double));
|
||
//uint32_t inp_buff[1024*2048] = {0,};
|
||
int ready_cnt = 0;
|
||
int ready_cnt_copy = 0;
|
||
uint32_t ready_cnt_Err = 0;
|
||
uint32_t recv_Err_code = 0;
|
||
|
||
|
||
printf("\nStart transparent mode\n");
|
||
BF_exec_cmd_simple(hnd, 0x8007, 10, 1); //start transparent
|
||
|
||
printf("\nFlushed from receiving buff: %d\n", X502_FlushRcv_buff(hnd));
|
||
|
||
printf("receiving data...\n");
|
||
|
||
|
||
//ready_cnt_Err = X502_GetRecvReadyCount(hnd, &ready_cnt_copy);
|
||
//recv_Err_code = X502_Recv(hnd, inp_buff, 1024, 10);
|
||
|
||
|
||
ready_cnt = ready_cnt_copy;
|
||
|
||
// printf("Ready count: %d, Err: %d \n", ready_cnt, ready_cnt_Err);
|
||
// printf("Recv Err code (<0 -- err, >= 0 -- number of received words(32bit)): %d\n", recv_Err_code);
|
||
|
||
if (recv_Err_code > 0){
|
||
ready_cnt = recv_Err_code;
|
||
}
|
||
if (ready_cnt < 0){
|
||
ready_cnt = 0;
|
||
}
|
||
|
||
int data_receive_trys_counter = 100;
|
||
uint32_t max_total_words = 100000;
|
||
// printf("\nflush TX buff. \n Number of free TX descriptors before flushing:");
|
||
// BF_exec_cmd_simple(hnd, 0x8010, 10, 1);
|
||
|
||
|
||
receive_to_file(hnd, logfilename, inp_buff, max_total_words);
|
||
|
||
//receive_data(hnd, logfilename, inp_buff, data_receive_trys_counter, max_total_words, DUMP_TO_FILE);
|
||
/*
|
||
data_receive_trys_counter = 100;
|
||
max_total_words = 10000;
|
||
|
||
receive_data(hnd, logfilename, inp_buff, data_receive_trys_counter, max_total_words, DUMP_TO_FILE);
|
||
*/
|
||
|
||
printf("\n\nget counters of calls of SPORT_RX, SPORT_TX, HDMA_RX, HDMA_TX\n");
|
||
BF_exec_cmd_with_arr(hnd, 0x8005U, 100, NULL, 0, 1);
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
printf("\nStart SEMITRANSPARENT mode\n");
|
||
BF_exec_cmd_simple(hnd, 0x800B, 2, 1); //start SEMITRANSPARENT
|
||
|
||
|
||
// printf("\nStart AVG mode\n");
|
||
// BF_exec_cmd_simple(hnd, 0x8008, 2, 1); //start averaging
|
||
|
||
|
||
// printf("\nflush TX buff. \n Number of free TX descriptors before flushing:");
|
||
// BF_exec_cmd_simple(hnd, 0x8010, 10, 1);
|
||
|
||
// X502_StreamsStop(hnd);
|
||
// X502_StreamsStart(hnd);
|
||
|
||
|
||
//BF_exec_cmd_simple(hnd, 0x8008, 2, 1); //start averaging
|
||
//BF_exec_cmd_simple(hnd, 0x8007, 2, 1); //start transparent
|
||
|
||
printf("\nFlushed from receiving buff: %d\n", X502_FlushRcv_buff(hnd));
|
||
|
||
|
||
|
||
|
||
// printf("\n\nget counters of calls of SPORT_RX, SPORT_TX, HDMA_RX, HDMA_TX\n");
|
||
// BF_exec_cmd_with_arr(hnd, 0x8005U, 100, NULL, 0, 1);
|
||
|
||
|
||
//fprintf(logfile_ptr, "value number; time, sec; adc_value, V\n");
|
||
|
||
|
||
data_receive_trys_counter = 100;
|
||
max_total_words = 100000;
|
||
|
||
// void receive_data(t_x502_hnd hnd, FILE* logfile_ptr, uint32_t* inp_buff, int data_receive_trys_counter, uint32_t max_total_words, DUMP_TO_FILE)
|
||
|
||
//printf("\n dbg value: ");
|
||
//BF_exec_cmd_simple(hnd, 0x800A, 10, 1);
|
||
|
||
struct timespec time_receive_started, time_receive_ended;
|
||
|
||
clock_gettime(CLOCK_MONOTONIC, &time_receive_started);
|
||
receive_to_file(hnd, logfilename, inp_buff, max_total_words);
|
||
// receive_data(hnd, logfilename, inp_buff, data_receive_trys_counter, max_total_words, FLUSH);
|
||
//receive_data(hnd, logfilename, inp_buff, data_receive_trys_counter, max_total_words, DUMP_TO_FILE);
|
||
clock_gettime(CLOCK_MONOTONIC, &time_receive_ended);
|
||
|
||
|
||
double receive_time = (time_receive_ended.tv_sec - time_receive_started.tv_sec);
|
||
receive_time += time_receive_ended.tv_nsec*1e-9;
|
||
receive_time += time_receive_started.tv_nsec*1e-9;
|
||
|
||
|
||
printf("\n Receive time: %g, %g sec/value \n", receive_time, receive_time/max_total_words);
|
||
|
||
|
||
// printf("\n dbg value: ");
|
||
// BF_exec_cmd_simple(hnd, 0x800A, 10, 1);
|
||
|
||
|
||
|
||
printf("\nStart transparent mode\n");
|
||
BF_exec_cmd_simple(hnd, 0x8007, 10, 1); //start transparent
|
||
|
||
printf("\nflush TX buff. \n Number of free TX descriptors before flushing:");
|
||
BF_exec_cmd_simple(hnd, 0x8010, 10, 1);
|
||
|
||
|
||
printf("\nFlushed from receiving buff: %d\n", X502_FlushRcv_buff(hnd));
|
||
|
||
// printf("\n dbg value: ");
|
||
// BF_exec_cmd_simple(hnd, 0x800A, 10, 1);
|
||
receive_data(hnd, logfilename, inp_buff, data_receive_trys_counter, max_total_words, DUMP_TO_FILE);
|
||
// printf("\n dbg value: ");
|
||
// BF_exec_cmd_simple(hnd, 0x800A, 10, 1);
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
printf("\nStart transparent mode\n");
|
||
BF_exec_cmd_simple(hnd, 0x8007, 2, 1); //start transparent
|
||
|
||
printf("\nflush TX buff. \n Number of free TX descriptors before flushing:");
|
||
BF_exec_cmd_simple(hnd, 0x8010, 10, 1);
|
||
|
||
printf("\nFlushed from receiving buff: %d\n", X502_FlushRcv_buff(hnd));
|
||
|
||
|
||
// printf("\n dbg value: ");
|
||
// BF_exec_cmd_simple(hnd, 0x800A, 10, 1);
|
||
receive_to_file(hnd, logfilename, inp_buff, max_total_words);
|
||
//receive_data(hnd, logfilename, inp_buff, data_receive_trys_counter, max_total_words, DUMP_TO_FILE);
|
||
printf("\n dbg value: ");
|
||
BF_exec_cmd_simple(hnd, 0x800A, 10, 1);
|
||
|
||
|
||
|
||
|
||
/*
|
||
while((--data_receive_trys_counter)&& (max_total_words)){
|
||
|
||
ready_cnt_Err = X502_GetRecvReadyCount(hnd, &ready_cnt);
|
||
recv_Err_code = X502_Recv(hnd, inp_buff, ready_cnt, 10);
|
||
printf("\n\nget counters of calls of SPORT_RX, SPORT_TX, HDMA_RX, HDMA_TX\n");
|
||
BF_exec_cmd_with_arr(hnd, 0x8005U, 100, NULL, 0, 1);
|
||
if (ready_cnt){
|
||
printf("Ready count: %d, Err: %d \n", ready_cnt, ready_cnt_Err);
|
||
for (int i = 0; i < ready_cnt; ++i){
|
||
//printf("\nabort value: %d\n", abort_crtl_C);
|
||
if (abort_crtl_C){
|
||
break;
|
||
}
|
||
--max_total_words;
|
||
if (max_total_words == 0){
|
||
break;
|
||
}
|
||
char bin_str_val[9] = {0,};
|
||
uin32_t_to_bin(inp_buff[i], bin_str_val);
|
||
printf(" 0x%08X,", inp_buff[i]);
|
||
fprintf(logfile_ptr, "0x%08X \n", inp_buff[i]);
|
||
//printf(" 0b%s,", bin_str_val);
|
||
++values_in_line;
|
||
if (values_in_line == 10){
|
||
printf("\n");
|
||
values_in_line = 0;
|
||
}
|
||
}
|
||
|
||
uint32_t process_data_Err = 0;
|
||
uint32_t adc_data_size = ready_cnt;
|
||
X502_Raw_User_Data_Parser(inp_buff, inp_values_N,
|
||
adc_data, adc_chans_N, adc_readouts_N,
|
||
&LFSM_res_tmp, &LFSM_res,
|
||
&FFT_res_tmp, &FFT_res);
|
||
//process_data_Err = X502_ProcessData(hnd, inp_buff, ready_cnt, X502_PROC_FLAGS_VOLT, adc_data, &adc_data_size, NULL, NULL);
|
||
uint64_t data_sum = 0;
|
||
for (int i = 0; i < ready_cnt; ++i){
|
||
data_sum += inp_buff[i];
|
||
if (i % 1000 == 1){
|
||
//printf(" %e\n", adc_data[i]);
|
||
}
|
||
}
|
||
|
||
}
|
||
//printf("try: %04d, words ready: %06d, receive_error_code: %05d, data_sum: %d \n", data_receive_trys_counter, ready_cnt, recv_Err_code, data_sum);
|
||
}
|
||
|
||
|
||
*/
|
||
|
||
|
||
//fclose(logfile_ptr);
|
||
|
||
|
||
printf("\n\nreceive done. Exiting...\n\n\n");
|
||
//logfile_ptr = fopen(logfilename, "w");
|
||
printf("dumped to file: %s\n", logfilename);
|
||
fprintf(stderr, "%s\n", logfilename);
|
||
|
||
X502_Close(hnd);
|
||
// освобождаем описатель
|
||
X502_Free(hnd);
|
||
return 0;
|
||
|
||
|
||
|
||
|
||
|
||
f_out = 1;
|
||
struct timespec time_started;
|
||
struct timespec time_ended;
|
||
timespec_get(&time_started, TIME_UTC);
|
||
float total_runs = 0.0;
|
||
long double delta_time = 0.0;
|
||
|
||
while(f_out != 1){
|
||
total_runs += 1.0;
|
||
|
||
X502_StreamsStart(hnd); //wait for trigger and start sampling
|
||
|
||
|
||
int32_t rcv_size;
|
||
uint32_t adc_size, din_size;
|
||
|
||
// массив для приема необработанных данных //
|
||
static uint32_t rcv_buf[READ_BLOCK_SIZE];
|
||
static double adc_data[READ_BLOCK_SIZE];
|
||
static uint32_t din_data[READ_BLOCK_SIZE];
|
||
|
||
// принимаем данные (по таймауту) //
|
||
rcv_size = X502_Recv(hnd, rcv_buf, READ_BLOCK_SIZE, READ_TIMEOUT);
|
||
timespec_get(&time_ended, TIME_UTC);
|
||
|
||
// результат меньше нуля означает ошибку //
|
||
if (rcv_size < 0) {
|
||
err = rcv_size;
|
||
fprintf(stderr, "Ошибка приема данных: %s\n", X502_GetErrorString(err));
|
||
} else if (rcv_size > 0) {
|
||
uint32_t first_lch;
|
||
// получаем номер логического канала, которому соответствует первый отсчет АЦП в массиве //
|
||
X502_GetNextExpectedLchNum(hnd, &first_lch);
|
||
|
||
adc_size = sizeof(adc_data)/sizeof(adc_data[0]);
|
||
din_size = sizeof(din_data)/sizeof(din_data[0]);
|
||
|
||
// обрабатываем принятые данные, распределяя их на данные АЦП и цифровых входов //
|
||
err = X502_ProcessData(hnd, rcv_buf, rcv_size, X502_PROC_FLAGS_VOLT,
|
||
adc_data, &adc_size, din_data, &din_size);
|
||
if (err != X502_ERR_OK) {
|
||
fprintf(stderr, "Ошибка обработки данных: %s\n", X502_GetErrorString(err));
|
||
} else {
|
||
uint32_t lch;
|
||
|
||
printf("Обработано данных АЦП = %d, цифровых входов = %d\n",
|
||
adc_size, din_size);
|
||
long double t_started = (long double)time_started.tv_sec + 1e-9*(long double)time_started.tv_nsec;
|
||
printf("started at %jd.%09ld or %Lg\n", (intmax_t)time_started.tv_sec, time_started.tv_nsec, t_started);
|
||
|
||
printf("received at %jd.%09ld \n", (intmax_t)time_ended.tv_sec, time_ended.tv_nsec);
|
||
|
||
delta_time = ((long double) time_ended.tv_sec - time_started.tv_sec ) + (((long double) time_ended.tv_nsec) * 1e-9 ) - (((long double) time_started.tv_nsec) * 1e-9 );
|
||
|
||
printf("delta time %Lg sec\n", delta_time);
|
||
// если приняли цифровые данные - выводим первый отсчет //
|
||
|
||
|
||
|
||
if (din_size != 0)
|
||
printf(" din_data = 0x%05X\n", din_data[0]);
|
||
|
||
// выводим по одному отсчету на канал. если обработанный блок
|
||
// начинается не с начала кадра, то в данном примере для
|
||
// вывода берем конец неполного кадра и начало следующего
|
||
for (lch=0; lch < ADC_LCH_CNT; lch++) {
|
||
// определяем позицию первого отсчета, соответствующего заданному логическому каналу:
|
||
// либо с конца не полного кадра, либо из начала следующего //
|
||
uint32_t pos = lch >= first_lch ? lch - first_lch : ADC_LCH_CNT-first_lch + lch;
|
||
if (pos <= adc_size) {
|
||
printf(" lch[%d]=%6.4f\n, pos=%d, adc_size=%d", lch, adc_data[pos], pos, adc_size);
|
||
|
||
time_t seconds;
|
||
time(&seconds);
|
||
|
||
FILE *fptr;
|
||
char filename[] = " ";
|
||
sprintf(&filename, "adc data %ld.csv", seconds);
|
||
fptr = fopen(filename, "w");
|
||
fprintf(fptr, "value number; time, sec; adc_value, V\n");
|
||
|
||
for (uint32_t data_pos; data_pos < adc_size; ++data_pos){
|
||
fprintf(fptr, "%d %6.7f %6.7f \n", data_pos, (double)data_pos / X502_REF_FREQ_2000KHZ , adc_data[data_pos]); //print whole data
|
||
|
||
//printf("%d %6.7f %6.7f \n", data_pos, (double)data_pos / X502_REF_FREQ_2000KHZ , adc_data[data_pos]); //print whole data
|
||
}
|
||
fclose(fptr);
|
||
|
||
} else {
|
||
printf(" lch[%d]= ---- \n", lch);
|
||
}
|
||
}
|
||
|
||
printf("\n");
|
||
fflush(stdout);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
X502_StreamsStop(hnd);
|
||
|
||
/*
|
||
xray =
|
||
|
||
//plot results. plotter code from: https://www.mps.mpg.de/1757268/exa_c#section_1
|
||
metafl ("cons");
|
||
scrmod ("revers");
|
||
disini ();
|
||
pagera ();
|
||
complx ();
|
||
axspos (450, 1800);
|
||
axslen (2200, 1200);
|
||
|
||
name ("X-axis", "x");
|
||
name ("Y-axis", "y");
|
||
|
||
labdig (-1, "x");
|
||
ticks (9, "x");
|
||
ticks (10, "y");
|
||
|
||
titlin ("Demonstration of CURVE", 1);
|
||
titlin ("SIN(X), COS(X)", 3);
|
||
|
||
ic = intrgb (0.95,0.95,0.95);
|
||
axsbgd (ic);
|
||
|
||
graf (0.0, 360.0, 0.0, 90.0, -1.0, 1.0, -1.0, 0.5);
|
||
setrgb (0.7, 0.7, 0.7);
|
||
grid (1, 1);
|
||
|
||
color ("fore");
|
||
height (50);
|
||
title ();
|
||
|
||
color ("red");
|
||
curve (xray, y1ray, n);
|
||
color ("green");
|
||
curve (xray, y2ray, n);
|
||
disfin ();
|
||
*/
|
||
--f_out;
|
||
|
||
|
||
|
||
#ifdef _WIN32
|
||
/* проверка нажатия клавиши для выхода */
|
||
if (err == X502_ERR_OK) {
|
||
if (_kbhit())
|
||
f_out = 1;
|
||
}
|
||
#else
|
||
{
|
||
// по нажатию Enter включаем/выключаем поток ADC
|
||
fd_set fds;
|
||
struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
|
||
|
||
FD_ZERO(&fds);
|
||
FD_SET(STDIN_FILENO, &fds);
|
||
if (select(1, &fds, NULL, NULL, &tv) == 1) {
|
||
int x;
|
||
static int adc_disabled = 0;
|
||
int ch;
|
||
|
||
if (adc_disabled) {
|
||
X502_StreamsEnable(hnd, X502_STREAM_ADC);
|
||
} else {
|
||
X502_StreamsDisable(hnd, X502_STREAM_ADC);
|
||
}
|
||
adc_disabled = !adc_disabled;
|
||
|
||
while(select(1, &fds, NULL, NULL, &tv) == 1) {
|
||
read(STDIN_FILENO, &ch, 1);
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
}
|
||
|
||
printf("delta time %Lg sec\n", delta_time);
|
||
printf("average run time %Lg sec\n", delta_time/total_runs);
|
||
// закрываем связь с модулем
|
||
X502_Close(hnd);
|
||
// освобождаем описатель
|
||
X502_Free(hnd);
|
||
}
|
||
return err;
|
||
}
|