From 068b026473607b472ccc25b4b39eec897a6e38ea Mon Sep 17 00:00:00 2001 From: Theodor Chikin Date: Thu, 17 Jul 2025 19:09:57 +0300 Subject: [PATCH] working receiving data and dumping it to file. Also implemented simple python plotter of that data. --- BF_companion | Bin 22072 -> 52624 bytes main.c | 540 +++++++++++++++++++++++++++++++++++++++------------ makefile | 2 +- plotter.py | 33 +++- 4 files changed, 445 insertions(+), 130 deletions(-) diff --git a/BF_companion b/BF_companion index 87443e80e367642586d86bf44daa4f413c234ce4..e6a5c29825a90a540661cd7c913f05df32798224 100755 GIT binary patch literal 52624 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 literal 22072 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 diff --git a/main.c b/main.c index 8902329..ec0505e 100644 --- a/main.c +++ b/main.c @@ -67,8 +67,61 @@ #include "l502_BF_enums.h" #include "l502_fpga_regs.h" +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 1 +#define ADC_LCH_CNT 4 // частота сбора АЦП в Гц// #define ADC_FREQ 2000000 @@ -91,11 +144,11 @@ // номера используемых физических каналов // -static uint32_t f_channels[ADC_LCH_CNT] = {0}; +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}; +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_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}; @@ -304,19 +357,26 @@ int32_t f_setup_params(t_x502_hnd hnd) { + //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); + 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 samping by external trigger + //X502_SetSyncStartMode(hnd, X502_SYNC_DI_SYN2_RISE); //start ADC sampling by external trigger //=======================================================// //for debug purposes: - X502_SetSyncMode(hnd, X502_SYNC_INTERNAL); - X502_SetSyncStartMode(hnd, X502_SYNC_INTERNAL); //start ADC samping after executing X502_StreamsStart() + 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 @@ -499,6 +559,223 @@ uint32_t BF_exec_cmd_with_arr(t_x502_hnd hnd, uint16_t cmd_code, uint32_t cmd_pa 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; + } + } + } +} + + + + + + + + + int main(int argc, char** argv) { @@ -523,6 +800,68 @@ int main(int argc, char** argv) { 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); @@ -557,6 +896,8 @@ int main(int argc, char** argv) { } + 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); @@ -571,6 +912,14 @@ int main(int argc, char** argv) { uint32_t bf_firmware_load_state = X502_BfLoadFirmware(hnd, BF_firmware_filename); //load firmware from l502-BFfirmware0.ldr file to BlackFin printf("load state: %u \n", bf_firmware_load_state); + 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; @@ -621,8 +970,8 @@ int main(int argc, char** argv) { //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 + //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 @@ -630,7 +979,7 @@ int main(int argc, char** argv) { //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 ); + streams_enable_Err = X502_StreamsEnable(hnd, X502_STREAM_ADC | X502_STREAM_DIN ); printf("Streams start err: %d \n", streams_enable_Err); uint32_t streams_start_Err = 0; streams_start_Err = X502_StreamsStart(hnd); @@ -643,7 +992,7 @@ int main(int argc, char** argv) { uint32_t waiting_cnt = 1; - waiting_cnt = 1000; + waiting_cnt = 100000; printf("\nwaiting %d ...", waiting_cnt); while(--waiting_cnt){;} //for(uint32_t timeout = 100000000; timeout; --timeout){;} @@ -660,7 +1009,9 @@ int main(int argc, char** argv) { printf("receiving data...\n"); - uint32_t inp_buff[1024] = {0,}; + 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,}; uint32_t ready_cnt = 0; uint32_t ready_cnt_Err = 0; @@ -674,13 +1025,26 @@ int main(int argc, char** argv) { 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; + } + + FILE *logfile_ptr; + time_t seconds; + time(&seconds); + char logfilename[] = " "; + sprintf(&logfilename, "received_data_%ld.csv", seconds); + logfile_ptr = fopen(logfilename, "w"); + printf("dumping to file: %c\n", logfilename); printf("\n\nreceived data:\n"); int values_in_line = 0; - for (int i = 0; i < 1024; ++i){ + //for (int i = 0; i < 1024; ++i){ + for (int i = 0; i < ready_cnt; ++i){ 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){ @@ -691,109 +1055,54 @@ int main(int argc, char** argv) { printf("\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); + //fprintf(logfile_ptr, "value number; time, sec; adc_value, V\n"); + int data_receive_trys_counter = 1000; + while(--data_receive_trys_counter){ + 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){ + 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; + } + } - - - - - - -/* - //uint16_t cmd_code = 0x80001U; - uint16_t cmd_code = 0x8001; //read ADC data - uint32_t par = 87; - const uint32_t snd_data[] = {1,1,2,2,3,4,5,56,67,23,1}; - 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; - - - - printf("TX cmd_code: 0x%X\n", cmd_code); - printf("TX tout: %u\n", tout); - printf("TX par: %u\n", par); - printf("TX snd_data size: %u\n", snd_size); - for (int i = 0; i < snd_size; ++i){ - printf(" %u,", snd_data[i]); - } - printf("\n"); - printf("TX rcv_size: %u\n", rcv_size); - - - BF_cmd_receive_code = X502_BfExecCmd (hnd, - cmd_code, - par, - snd_data, - snd_size, - rcv_data, - rcv_size, - tout, - &recvd_size); - - - 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,", rcv_data[i]); - } - printf("\n\n\n\n"); - - - - - - cmd_code = 0x8002; - par = 87; - //snd_data[] = {1,1,2,2,3,4,5,56,67,23,1}; - snd_size = 11; - //rcv_data[13] = {0,}; - rcv_size = 13; - tout = 1; - recvd_size = 0; - - - - printf("TX cmd_code: 0x%X\n", cmd_code); - printf("TX tout: %u\n", tout); - printf("TX par: %u\n", par); - printf("TX snd_data size: %u\n", snd_size); - for (int i = 0; i < snd_size; ++i){ - printf(" %u,", snd_data[i]); - } - printf("\n"); - printf("TX rcv_size: %u\n", rcv_size); - - - BF_cmd_receive_code = X502_BfExecCmd (hnd, - cmd_code, - par, - snd_data, - snd_size, - rcv_data, - rcv_size, - tout, - &recvd_size); - - - 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(" %u,", rcv_data[i]); - } - printf("\n"); - -*/ - + /* + 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); @@ -806,13 +1115,6 @@ int main(int argc, char** argv) { -// // запуск синхронного ввода-вывода // -// if (err == X502_ERR_OK) { -// err = X502_StreamsStart(hnd); -// if (err != X502_ERR_OK) -// fprintf(stderr, "Ошибка запуска сбора данных: %s!\n", X502_GetErrorString(err)); -// } - f_out = 1; struct timespec time_started; diff --git a/makefile b/makefile index 6c16bb5..2ec8ae0 100644 --- a/makefile +++ b/makefile @@ -45,6 +45,6 @@ endif all: - $(CC) main.c $(FLAGS) -ll502api -le502api -lx502api -o BF_companion + $(CC) main.c $(FLAGS) -ll502api -le502api -lx502api -g -o BF_companion clean: -rm BF_companion diff --git a/plotter.py b/plotter.py index e747066..15711fa 100755 --- a/plotter.py +++ b/plotter.py @@ -15,21 +15,34 @@ if __name__ == "__main__": main() else: f = open(argv[1], "rt") - f.readline() - X = [] - Y = [] + data = {} + values_N = 0 for line in f: + print(line) + #print(line, len(line)) + len_line = len(line) try: - i, x, y = line.split() - x = float(x) - y = float(y) - X.append(x) - Y.append(y) + if (len_line >= 11): + if (line[:2] == "0x"): + values_N += 1 + header = line[2:4] + value = line[4:10] + if not(header in data): + data[header] = [] + data[header + "_N"] = [] + data[header + "_hex"] = [] + data[header].append(int(value,16)) + data[header + "_hex"].append(value) + data[header + "_N"].append(values_N) except ValueError: pass + except IndexError: + pass f.close() - print("data samples:",len(X)) +# print("data samples:",len(data["X"])) chart = go.Figure() - chart.add_trace(go.Scatter(x=X, y=Y)) + for key, val in data.items(): + if (key.count("_N") + key.count("_hex")) == 0: + chart.add_trace(go.Scatter(x=data[key+"_N"], y=data[key], name=key, mode="lines+markers", text=data[key+"_hex"])) chart.show()