initial commit. Thereis an old software for configuring and reading data from ADC in a RagiPhotonic generator
This commit is contained in:
BIN
BF_companion
Executable file
BIN
BF_companion
Executable file
Binary file not shown.
1
l502-BFfirmware0.ldr
Symbolic link
1
l502-BFfirmware0.ldr
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../BFfirmware_0/build/release/bin/l502-BFfirmware0.ldr
|
||||||
585
main.c
Normal file
585
main.c
Normal file
@ -0,0 +1,585 @@
|
|||||||
|
/* Данный пример представляет из себя консольную программу на языке 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>
|
||||||
|
|
||||||
|
// количество используемых логических каналов //
|
||||||
|
#define ADC_LCH_CNT 1
|
||||||
|
|
||||||
|
// частота сбора АЦП в Гц//
|
||||||
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
// номера используемых физических каналов //
|
||||||
|
static uint32_t f_channels[ADC_LCH_CNT] = {0};
|
||||||
|
// режимы измерения для каналов //
|
||||||
|
static uint32_t f_ch_modes[ADC_LCH_CNT] = {X502_LCH_MODE_COMM};
|
||||||
|
// диапазоны измерения для каналов //
|
||||||
|
static uint32_t f_ch_ranges[ADC_LCH_CNT] = {X502_ADC_RANGE_1};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// признак необходимости завершить сбор данных //
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* Функция находит все подключенные модули по интерфейсам 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);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
X502_SetSyncMode(hnd, X502_SYNC_DI_SYN1_FALL);
|
||||||
|
|
||||||
|
//set ADC sample frequency from internal generator with frequency 2 MHz
|
||||||
|
//X502_SetRefFreq(hnd, X502_REF_FREQ_2000KHZ);
|
||||||
|
|
||||||
|
|
||||||
|
X502_SetSyncStartMode(hnd, X502_SYNC_DI_SYN2_RISE); //start ADC samping by external trigger
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// записываем настройки в модуль //
|
||||||
|
if (err == X502_ERR_OK)
|
||||||
|
err = X502_Configure(hnd, 0);
|
||||||
|
|
||||||
|
// разрешаем синхронные потоки //
|
||||||
|
if (err == X502_ERR_OK) {
|
||||||
|
err = X502_StreamsEnable(hnd, X502_STREAM_ADC);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
////******* Получение списка устройств и выбор, с каким будем работать *****************//
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (err == X502_ERR_OK) {
|
||||||
|
// настраиваем параметры модуля //
|
||||||
|
err = f_setup_params(hnd);
|
||||||
|
if (err != X502_ERR_OK)
|
||||||
|
fprintf(stderr, "Ошибка настройки модуля: %s!", X502_GetErrorString(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // запуск синхронного ввода-вывода //
|
||||||
|
// if (err == X502_ERR_OK) {
|
||||||
|
// err = X502_StreamsStart(hnd);
|
||||||
|
// if (err != X502_ERR_OK)
|
||||||
|
// fprintf(stderr, "Ошибка запуска сбора данных: %s!\n", X502_GetErrorString(err));
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
f_out = 2;
|
||||||
|
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;
|
||||||
|
}
|
||||||
48
makefile
Normal file
48
makefile
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# makefile для сборки примера с помощью компиляторов mingw (под Windows)
|
||||||
|
# или GCC (под Linux). Необходимо определить 3 переменные:
|
||||||
|
#
|
||||||
|
# CC - имя команды для вызова компилятора
|
||||||
|
# X502API_LIBRARIES_DIR - путь к файлм .a или .so библиотек l502api, e502api, x502api (если не стандартный)
|
||||||
|
# X502API_INCLUDE_DIR - путь к заголовочным файлам l502api.h, e502api.h, x502api.h
|
||||||
|
#
|
||||||
|
# Ниже приведено несколько примеров в закоментированном виде
|
||||||
|
|
||||||
|
#--- Linux с заголовками и библиотекой в стандартных директориях: компилятор GCC
|
||||||
|
#CC = gcc
|
||||||
|
|
||||||
|
#--- Вариант запуска из MSYS со стандартным 32-битным mingw
|
||||||
|
#CC = gcc
|
||||||
|
#X502API_LIBRARIES_DIR = "/c/Program Files/L-Card/lpcie/lib/mingw"
|
||||||
|
#X502API_INCLUDE_DIR = "/c/Program Files/L-Card/lpcie/include"
|
||||||
|
|
||||||
|
|
||||||
|
#--- 64-битный вариант mingw w64, идущий вместе с cygwin --------
|
||||||
|
#CC = x86_64-w64-mingw32-gcc
|
||||||
|
#X502API_LIBRARIES_DIR = "/cygdrive/c/Program Files (x86)/L-Card/lpcie/lib/mingw64"
|
||||||
|
#X502API_INCLUDE_DIR = "/cygdrive/c/Program Files (x86)/L-Card/lpcie/include"
|
||||||
|
|
||||||
|
#--- 32-битный вариант mingw w64, идущий вместе с cygwin --------
|
||||||
|
#CC = i686-w64-mingw32-gcc
|
||||||
|
#X502API_LIBRARIES_DIR = "/cygdrive/c/Program Files (x86)/L-Card/lpcie/lib/mingw"
|
||||||
|
#X502API_INCLUDE_DIR = "/cygdrive/c/Program Files (x86)/L-Card/lpcie/include"
|
||||||
|
|
||||||
|
#--- 32-битный вариант mingw, идущий вместе с cygwin --------
|
||||||
|
#CC = i686-pc-mingw32-gcc
|
||||||
|
#X502API_LIBRARIES_DIR = "/cygdrive/c/Program Files (x86)/L-Card/lpcie/lib/mingw"
|
||||||
|
#X502API_INCLUDE_DIR = "/cygdrive/c/Program Files (x86)/L-Card/lpcie/include"
|
||||||
|
|
||||||
|
|
||||||
|
FLAGS =
|
||||||
|
|
||||||
|
ifdef X502API_LIBRARIES_DIR
|
||||||
|
FLAGS += -L $(X502API_LIBRARIES_DIR)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef X502API_INCLUDE_DIR
|
||||||
|
FLAGS += -I $(X502API_INCLUDE_DIR)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
all:
|
||||||
|
$(CC) main.c $(FLAGS) -ll502api -le502api -lx502api -o BF_companion
|
||||||
35
plotter.py
Executable file
35
plotter.py
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/pypy3
|
||||||
|
import plotly.graph_objs as go
|
||||||
|
from decimal import *
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
chart = go.Figure()
|
||||||
|
chart.add_trace(go.Scatter(x=[1,2,3], y=[1,2,3]))
|
||||||
|
chart.show()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(argv) == 1:
|
||||||
|
main()
|
||||||
|
else:
|
||||||
|
f = open(argv[1], "rt")
|
||||||
|
f.readline()
|
||||||
|
X = []
|
||||||
|
Y = []
|
||||||
|
for line in f:
|
||||||
|
try:
|
||||||
|
i, x, y = line.split()
|
||||||
|
x = float(x)
|
||||||
|
y = float(y)
|
||||||
|
X.append(x)
|
||||||
|
Y.append(y)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
f.close()
|
||||||
|
print("data samples:",len(X))
|
||||||
|
chart = go.Figure()
|
||||||
|
chart.add_trace(go.Scatter(x=X, y=Y))
|
||||||
|
chart.show()
|
||||||
|
|
||||||
Reference in New Issue
Block a user