Files
E502_ADC_BF_PC_companion/main.c

1046 lines
40 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Данный пример представляет из себя консольную программу на языке 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"
/* Remove unused enums/structs and constants that are not referenced anywhere */
// количество используемых логических каналов //
#define ADC_LCH_CNT 1
/* Unused frequency/timing defines removed */
// сколько отсчетов считываем за блок //
#define READ_BLOCK_SIZE 4096*200
// таймаут на прием блока (мс) //
#define READ_TIMEOUT 2000
/* Unused BF user command define removed */
// номера используемых физических каналов //
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_02, 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;
typedef enum {
RUN_MODE_TEST = 0,
RUN_MODE_FINITE = 1,
RUN_MODE_INF = 2
} run_mode_t;
typedef enum {
BF_MODE_TRANSPARENT = 0,
BF_MODE_AVG = 1
} bf_mode_t;
typedef struct main_state_typedef{
run_mode_t run_mode; // TEST, FINITE_RUN, INF_RUN
bf_mode_t BF_mode; // TRANSPARENT, AVG
uint32_t run_length; // in ms. Used as timeout for receive_to_file
uint32_t run_I; // № current run
uint32_t runs_N; // total number of runs
} main_state;
static void main_state_set_defaults(main_state* st) {
st->run_mode = RUN_MODE_TEST;
st->BF_mode = BF_MODE_TRANSPARENT;
st->run_length = 1000;
st->run_I = 0;
st->runs_N = 1;
}
static char* f_trim(char* s) {
char* end;
while (*s==' ' || *s=='\t' || *s=='\r' || *s=='\n') s++;
if (*s == 0) return s;
end = s + strlen(s) - 1;
while (end > s && (*end==' ' || *end=='\t' || *end=='\r' || *end=='\n')) end--;
end[1] = '\0';
return s;
}
static void parse_cmd_file(const char* filename, main_state* st) {
FILE* f = fopen(filename, "r");
if (f == NULL) {
printf("Command file '%s' not found. Using defaults.\n", filename);
return;
}
char line[512];
while (fgets(line, sizeof(line), f)) {
char* p = line;
char* comment = strstr(p, "//");
if (comment) *comment = '\0';
p = f_trim(p);
if (*p == '\0') continue;
char* field = strtok(p, "\t \r\n");
char* value = strtok(NULL, "\t \r\n");
if (!field || !value) continue;
if (strcmp(field, "run_mode") == 0) {
if (strcmp(value, "FINITE_RUN") == 0) {
st->run_mode = RUN_MODE_FINITE;
} else if (strcmp(value, "INF_RUN") == 0) {
st->run_mode = RUN_MODE_INF;
} else if (strcmp(value, "TEST") == 0) {
st->run_mode = RUN_MODE_TEST;
} else {
st->run_mode = RUN_MODE_TEST; // default on mismatch
}
} else if (strcmp(field, "BF_mode") == 0) {
if (strcmp(value, "TRANSPARENT") == 0) {
st->BF_mode = BF_MODE_TRANSPARENT;
} else if (strcmp(value, "AVG") == 0) {
st->BF_mode = BF_MODE_AVG;
} else {
st->BF_mode = BF_MODE_TRANSPARENT; // default on mismatch
}
} else if (strcmp(field, "run_length") == 0) {
char* endp = NULL;
unsigned long v = strtoul(value, &endp, 0);
if (endp != value) st->run_length = (uint32_t)v;
} else if (strcmp(field, "runs_N") == 0) {
char* endp = NULL;
unsigned long v = strtoul(value, &endp, 0);
if (endp != value) st->runs_N = (uint32_t)v;
} else if (strcmp(field, "run_I") == 0) {
char* endp = NULL;
unsigned long v = strtoul(value, &endp, 0);
if (endp != value) st->run_I = (uint32_t)v;
}
}
fclose(f);
}
/* Unused SIGINT handler and flag removed */
/* Функция находит все подключенные модули по интерфейсам 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;
}
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 insert_marker_to_file(char* logfilename, char* marker_text){
printf("marker %s <======================================\n", marker_text);
FILE* logfile_ptr = fopen(logfilename, "a");
fprintf(logfile_ptr, "marker %s \n", marker_text);
fclose(logfile_ptr);
}
void receive_to_file(t_x502_hnd hnd, char* logfilename, uint32_t* inp_buff, uint32_t max_total_words, uint32_t timeout){
FILE* logfile_ptr = fopen(logfilename, "a");
// fprintf(logfile_ptr, "0xFF00000 \n");
// fprintf(logfile_ptr, "0xFFFFFFF \n");
// fprintf(logfile_ptr, "0xFF00000 \n");
// uint32_t timeout = 100;
uint32_t recv_Err_code = X502_Recv(hnd, inp_buff, max_total_words, timeout);
//uint32_t recv_Err_code = X502_Recv(hnd, inp_buff, max_total_words, 20000);
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);
}
int main(int argc, char** argv) {
int32_t err = X502_ERR_OK;
uint32_t ver;
t_x502_hnd hnd = NULL;
// читаем имя командного файла из аргументов CLI
const char* cmd_filename = "default.cmd";
if (argc > 1 && argv[1] != NULL && argv[1][0] != '\0') {
cmd_filename = argv[1];
}
// получаем версию библиотеки //
ver = X502_GetLibraryVersion();
printf("Версия библиотеки: %d.%d.%d\n", (ver >> 24)&0xFF, (ver>>16)&0xFF, (ver>>8)&0xFF);
printf("Command file: %s\n", cmd_filename);
// загружаем состояние из командного файла
main_state state;
main_state_set_defaults(&state);
parse_cmd_file(cmd_filename, &state);
// отладочный вывод принятых значений
printf("Parsed state: run_mode=%d, BF_mode=%d, run_length=%u, runs_N=%u, run_I=%u\n",
(int)state.run_mode, (int)state.BF_mode, state.run_length, state.runs_N, state.run_I);
/* Removed unused temporary buffers and FFT/LFSM placeholders */
////******* Получение списка устройств и выбор, с каким будем работать *****************//
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));
}
printf("\n\n\n");
//setup ADC:
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);
if (state.run_mode == RUN_MODE_FINITE){
state.run_I = 0;
char tmp_data_filename[] = " ";
struct timespec ts;
uint32_t max_total_words = 0;
uint32_t *inp_buff = malloc(1024*100*1024*2*4);
while(state.run_I < state.runs_N){
max_total_words = 10000000;
timespec_get(&ts, TIME_UTC);
// sprintf(&tmp_data_filename, "tmp/received_data_%ld.%ld.csv", ts.tv_sec, ts.tv_nsec);
// sprintf(&logfilename, "tmp/received_data_%ld.%ld.csv", ts.tv_sec, ts.tv_nsec);
//sprintf(&logfilename, "data/received_data_%ld.csv", seconds);
snprintf(tmp_data_filename, sizeof(tmp_data_filename), "tmp/received_data_%ld.%ld.csv", ts.tv_sec, ts.tv_nsec);
printf("%u/%u dumping to file: %s\n", (unsigned)state.run_I, (unsigned)state.runs_N, tmp_data_filename);
receive_to_file(hnd, tmp_data_filename, inp_buff, max_total_words, state.run_length);
state.run_I++;
}
free(inp_buff);
X502_Close(hnd);
// освобождаем описатель
X502_Free(hnd);
return 0;
}else if (state.run_mode == RUN_MODE_INF){
state.run_I = 0;
char tmp_data_filename[] = " ";
struct timespec ts;
uint32_t max_total_words = 0;
uint32_t *inp_buff = malloc(1024*100*1024*2*4);
while (1){ //should be infinite. because it is RUN_MODE_INF
//while(state.run_I < state.runs_N){
max_total_words = 10000000;
timespec_get(&ts, TIME_UTC);
// sprintf(&tmp_data_filename, "tmp/received_data_%ld.%ld.csv", ts.tv_sec, ts.tv_nsec);
// sprintf(&logfilename, "tmp/received_data_%ld.%ld.csv", ts.tv_sec, ts.tv_nsec);
//sprintf(&logfilename, "data/received_data_%ld.csv", seconds);
snprintf(tmp_data_filename, sizeof(tmp_data_filename), "tmp/received_data_%ld.%ld.csv", ts.tv_sec, ts.tv_nsec);
printf("%u dumping to file: %s\n", (unsigned)state.run_I, tmp_data_filename);
receive_to_file(hnd, tmp_data_filename, inp_buff, max_total_words, state.run_length);
state.run_I++;
}
free(inp_buff);
X502_Close(hnd);
// освобождаем описатель
X502_Free(hnd);
return 0;
}else{ //TEST mode as default
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,};
/* Removed unused counters */
insert_marker_to_file(logfilename, "start transparent");
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");
/* Removed unused readiness checks */
uint32_t max_total_words = 100000;
/* Removed unused data_receive_trys_counter */
// 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, 10000);
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);
//*
insert_marker_to_file(logfilename, "start AVG");
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);
// for(uint32_t wait_i = 1e6; wait_i; --wait_i){;}
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");
max_total_words = 100000;
//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, 10000);
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);
insert_marker_to_file(logfilename, "start transparent");
printf("\nStart transparent mode\n");
BF_exec_cmd_simple(hnd, 0x8007, 2, 1); //start transparent
X502_StreamsStop(hnd);
X502_StreamsStart(hnd);
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, 10000);
printf("\n dbg value: ");
BF_exec_cmd_simple(hnd, 0x800A, 10, 1);
//*/
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;
}
}
return -1;
}