/***************************************************************************//** @addtogroup user_process @{ @file l502_user_process.c Файл содержит простейший вариант реализации пользовательских функций, в котором потоки данных передаются без изменения и никакие пользовательские команды не обрабатываются. Пользователь может изменить этот файл и добавить здесь свою обработку. *******************************************************************************/ #include "l502_stream.h" #include "l502_hdma.h" #include "l502_sport_tx.h" #include "l502_cmd.h" #include #include "l502_defs.h" // import defines of constants #include "l502_params.h" #include "l502_stream.h" #include "l502_user_process.h" uint32_t streams_cnt[4] = {0,}; #define LFSM_val_ON 0b01100111 #define LFSM_val_OFF 0b01101000 #define LFSM_val_X 0b01101001 //#define TX_BUFF_SIZE 1024*1024 //#define TX_BUFF_SIZE 1000 #define LFSM_BUFF_SIZE 1000 #define LFSM_DATALEN 1024 #define dbg_sport_rx_copy_size 10 //#define LFSM_DATALEN 1024 //#pragma section("sdram_noinit", NO_INIT) //#include "l502_sdram_noinit.h" //__attribute__((section(".sdram_noinit"), far)) //static volatile uint32_t dbg_sport_rx_copy[TX_BUFF_SIZE]; //uint32_t dbg_sport_rx_copy[TX_BUFF_SIZE];// = {0,}; uint32_t dbg_sport_rx_copy[dbg_sport_rx_copy_size];// = {0,}; //* //#include "l502_sdram_noinit.h" //static volatile uint32_t LFSM_data[LFSM_DATALEN] = {0,}; //#include "l502_sdram_noinit.h" //static volatile uint32_t TX_buff[TX_BUFF_SIZE]; //static volatile uint32_t TX_buff[TX_BUFF_SIZE] __attribute__((section(".sdram_noinit"))); //static volatile uint32_t TX_buff[10000] __attribute__((section(".sdram_noinit"))); //static volatile uint32_t TX_buff[10000]; //static volatile uint32_t // = {0,}; uint32_t streams_succes_flag = 0; /* struct dataprocess_typedef { uint8_t config = 0; uint32_t datapoints_max_N = 0; uint32_t datapoint_curr_I = 0; uint32_t data_raw; }; */ extern volatile uint32_t TX_buff[]; //size: TX_BUFF_SIZE //extern volatile uint32_t RAW_data_buff[]; //size: RAW_DATA_BUFF_SIZE extern volatile uint32_t AVG_buff[]; //size: AVG_BUFF_SIZE //extern volatile uint32_t FFT_buff[]; //size: FFT_BUFF_SIZE volatile struct dataprocessor_dypedef{ uint8_t mode; uint8_t mode_next; uint8_t cycle_state; uint8_t LFSM_state; // 0 -- waiting for it... ; 1 -- receiving LFSM data uint16_t average_N_max; uint16_t average_N; uint32_t TX_buff_I; uint8_t TX_buff_state; //0 --blocked, 1 -- filling, 2 -- ready to send uint32_t AVG_buff_I; uint8_t AVG_buff_state; uint32_t FFT_buff_I; uint8_t FFT_buff_state; uint32_t digital_word_prev; uint32_t digital_word_curr; uint8_t DIN2_SYN_value_curr; uint8_t DIN2_SYN_value_prev; }Proc_state; volatile uint32_t TX_buff_I = 0; volatile uint32_t TX_buff_I_shadow = 123321; volatile uint32_t data_I = 0; volatile uint32_t send_size = 0; //int f_sport_test(void); void l502_stream_init(void); //struct LFSM_typedef{ // uint8_t //}; uint8_t LFSM_started = 0; uint8_t DY_SYN_2_value = 0; uint8_t DY_SYN_2_value_prev = 0; /***************************************************************************//** @brief Обработка принятого массива данных АЦП/DIN. Функция вызывается каждый раз, когда обнаружены новые данные от АЦП/цифровых входов, пришедшие по SPORT0. Функция должна обработать данные и вернуть количество обработанных данных, однако эти данные все еще считаются использованными (не могут быть переписаны новыми пришедшими данными) до тех пор пока не будет вызвана функция stream_in_buf_free()). Если функция вернет значение меньше чем size, то функция будут вызванна при следующем проходе еще раз с указателем на необработанные данные. В текущей реализации просто запускается передача данных по HDMA в ПК @param[in] data Указатель на массив с принятыми данными @param[in] size Количество принятых данных в 32-битных словах @return Функция возвращает количество обработанных данных (от 0 до size). На эти данные не будет вызываться повторно usr_in_proc_data(), но они считаются еще используемыми *******************************************************************************/ uint32_t usr_in_proc_data(uint32_t* data, uint32_t size) { /* если есть свободные дескрипторы на передачу по HDMA - ставим блок на передачу. Иначе возвращаем 0, чтобы на обработку этих данных функцию вызвали бы позже */ ++streams_cnt[0]; /* for (int i = 0; i < TX_BUFF_SIZE; ++i){ TX_buff[i] = 0x00000000; } */ //for (int i = 0; i < dbg_sport_rx_copy; ++i){ // dbg_sport_rx_copy[i] = data[i]; //} //* //simple transparent mode if (Proc_state.mode == TRANSPARENT){ data_I = 0; while((data_I < size )&& (TX_buff_I < TX_BUFF_SIZE)){ TX_buff[TX_buff_I++] = data[data_I++]; } } if (Proc_state.mode == AVG){ data_I = 0; //TX_buff_I = 0; Proc_state.AVG_buff_I = 0; while((data_I < size )&& (Proc_state.AVG_buff_I < AVG_BUFF_SIZE)){ //uint32_t word = data[data_I]; //uint32_t avg_word = AVG_buff[Proc_state.AVG_buff_I++]; //AVG_buff[Proc_state.AVG_buff_I] = (avg_word & 0x00FFFFFF) + (word & 0x00FFFFFF); //AVG_buff[Proc_state.AVG_buff_I++] = data[data_I++]; AVG_buff[Proc_state.AVG_buff_I] = data[data_I]; Proc_state.AVG_buff_I++; data_I++; } //Proc_state.AVG_buff_I = 0; } /*/ if (Proc_state.mode == AVG){ uint32_t data_I = 0; while((data_I < size )&& (TX_buff_I < (TX_BUFF_SIZE - 1))){ // TX_buff[TX_buff_I++] = data[data_I++]; uint32_t word = data[data_I++]; TX_buff[TX_buff_I++] = (word & 0x00FFFFFF);// | 0xDE000000; //TX_buff[TX_buff_I++] = ((word & 0x00FFFFFF) | 0xDE000000); //TX_buff[TX_buff_I++] = 0xADEFDEED; } } //*/ //* // if (Proc_state.mode == AVG){ //TX_buff_I = 10; /* uint32_t data_I = 0; uint8_t new_cycle_started = 0; uint8_t cycle_cont = 1; while ((data_I < size) && (Proc_state.AVG_buff_I < AVG_BUFF_SIZE) && cycle_cont ){ uint32_t word = data[data_I]; uint32_t val = word & 0x00FFFFFF; uint8_t header = (uint8_t)(word >> 24); */ /* if (header == 0x00){ Proc_state.digital_word_prev = Proc_state.digital_word_curr; Proc_state.digital_word_curr = word; DY_SYN_2_value_prev = DY_SYN_2_value; if (word & 0b1 << 17){ DY_SYN_2_value = 1; }else{ DY_SYN_2_value = 0; } if ((DY_SYN_2_value == 1)&& (DY_SYN_2_value_prev == 0)){ //new cycle started new_cycle_started = 1; } } //*/ /* if (header == 0xD0){ //it`s first channel if (new_cycle_started){ new_cycle_started = 0; ++Proc_state.average_N; if (Proc_state.average_N >= Proc_state.average_N_max){ Proc_state.mode == AVG_DONE; cycle_cont = 0; //break averaging cycle Proc_state.AVG_buff_I = 0; } }else{ if (Proc_state.AVG_buff_I < AVG_BUFF_SIZE){ AVG_buff[Proc_state.AVG_buff_I] =(word & 0x00FFFFFF);// | 0xDE000000; //uint32_t tmp = AVG_buff[Proc_state.AVG_buff_I]; //tmp += val; //tmp &= 0x0FFFFFFF; //AVG_buff[Proc_state.AVG_buff_I] = tmp | (0x40000000 & 0xF0000000); //set header (first 4 bits) to 0x4 -- average (0x4 -- average) Proc_state.AVG_buff_I++; } } } data_I++; //*/ // AVG_buff[Proc_state.AVG_buff_I] = 0xDDDDDDDD; //TX_buff[TX_buff_I++] = data[data_I]; //TX_buff[TX_buff_I++] = 0xEEEEEEEE; // data_I++; // Proc_state.AVG_buff_I++; //} // if (Proc_state.AVG_buff_I == AVG_BUFF_SIZE){ /* if (Proc_state.AVG_buff_I >= 10){ Proc_state.AVG_buff_I = 10; Proc_state.mode == AVG_DONE; } */ // } /* if(Proc_state.mode == AVG_DONE){ //TODO: if (Proc_state.TX_buff_state == 0){ Proc_state.TX_buff_state = 1; //0 --ready, 1 -- filling, 2 -- ready to send // Proc_state.AVG_buff_state = 1; //0 -- ready, 1 -- blocked, uint32_t max_I = TX_BUFF_SIZE; if (max_I > AVG_BUFF_SIZE){ max_I = AVG_BUFF_SIZE; } for (uint32_t I = 0; I < max_I; ++I){ if (TX_buff_I < TX_BUFF_SIZE){ ++TX_buff_I; } TX_buff[TX_buff_I] = AVG_buff[I]; AVG_buff[I] = 0; } Proc_state.TX_buff_state = 2; //0 --ready, 1 -- filling, 2 -- ready to send } Proc_state.mode = Proc_state.mode_next; } //*/ /* uint32_t radar_word_I = 0; //uint32_t TX_buff_I = 0; uint32_t word_prev = 0; uint32_t digital_word_prev = 0; for (int data_I = 0; (data_I < size) && (TX_buff_I < TX_BUFF_SIZE); ++data_I){ uint32_t word = data[data_I]; uint32_t val = word & 0x00FFFFFF; uint8_t header = (uint8_t)(word >> 24); //11010000 if (((header & 0b10000000) == 0b10000000)){ //it`s ADC word if (header == 0XD0){ //phy channel № 1 in common mode //TX_buff[TX_buff_I++] = ((0b01100000 & LFSM_val_ON) << 24) & val; TX_buff[TX_buff_I++] = 0xD0ADEFEA; //TX_buff[TX_buff_I++] = word; }else if (header == 0xD1){//phy channel № 2 in common mode TX_buff[TX_buff_I++] = word; //TX_buff[TX_buff_I++] = ((0b01100000 & LFSM_val_OFF) << 24) & val; //TX_buff[TX_buff_I++] = 0xD0ADEFEB; }else{ //TX_buff[TX_buff_I++] = word; TX_buff[TX_buff_I++] = word; //TX_buff[TX_buff_I++] = 0xD0AAAAAA; } } else if ( header == 0b00000000){ //it`s digital //if ((word & 0x2200) == 0x2200){ TX_buff[TX_buff_I++] = word; //TX_buff[TX_buff_I++] = 0xAD000000; //detect rise on DI_SYN2 -- start of chirp if (word & 0b1 << 17){ DY_SYN_2_value = 1; }else{ DY_SYN_2_value = 0; } if ((DY_SYN_2_value == 1)&& (DY_SYN_2_value_prev == 0)){ TX_buff[TX_buff_I++] = 0xAD000000; } DY_SYN_2_value_prev = DY_SYN_2_value; digital_word_prev = word; } else{ // TX_buff[TX_buff_I++] = word; } word_prev = word; // }else if ((header & 0b00000000) == ){ // }else if ((header & 0b00000000) == ){ // }else if ((header & 0b00000000) == ){ // }else if ((header & 0b00000000) == ){ // }else if ((header & 0b00000000) == ){ } */ //stream_in_buf_free(size); /* //int i = 0; //uint8_t //while for (int i = 0; i < LFSM_DATALEN; ++i){ uint32_t msg; if (i % 2){ msg = (LFSM_val_ON << 24) + data[i]; }else{ msg = (LFSM_val_OFF << 24) + data[i]; } LFSM_data[i] = msg; } */ if (hdma_send_req_rdy()) { //streams_cnt[0] /* if (Proc_state.TX_buff_state == 2){ hdma_send_req_start(TX_buff, TX_BUFF_SIZE, 0); }else if(0){ }else{ hdma_send_req_start(TX_buff, TX_buff_I, 0); TX_buff_I = 0; //hdma_send_req_start(data, size, 0); } */ /* if (Proc_state.mode == AVG_DONE){ uint32_t send_size = Proc_state.AVG_buff_I; // uint32_t send_size = AVG_BUFF_SIZE; hdma_send_req_start(AVG_buff, send_size, 0); Proc_state.mode = AVG; return send_size; } //*/ if (Proc_state.mode == AVG){ send_size = Proc_state.AVG_buff_I; //send_size = TX_buff_I; //uint32_t send_size = AVG_BUFF_SIZE; hdma_send_req_start(AVG_buff, send_size, 0); return send_size; }else{ hdma_send_req_start(TX_buff, TX_buff_I, 0); TX_buff_I_shadow = TX_buff_I; TX_buff_I = 0; return TX_buff_I_shadow; } //hdma_send_req_start(data, size, 0); //streams_cnt[0] = hdma_send_req_start(LFSM_data, LFSM_DATALEN, 0); //return size; } return 0; } /***************************************************************************//** @brief Обработка принятого массива с данными ЦАП/DOUT Функция вызывается каждый раз, когда обнаружены новые данные, принятые от ПК по HDMA. Функция должна обработать данные и вернуть количество обработанных данных, однако эти данные все еще считаются использованными (не могут быть переписаны новыми пришедшими данными) до тех пор пока не будет вызвана функция stream_out_buf_free()). Если функция вернет значение меньше чем size, то функция будут вызвана после еще раз с указателем на необработанные данные. В текущей реализации просто запускается передача данных по SPORT для вывода на ЦАП/цифровые выходы. @param[in] data Указатель на массив с принятыми данными @param[in] size Количество принятых данных в 32-битных словах @return Функция возвращает количество обработанных данных (от 0 до size). На эти данные не будет вызываться повторно usr_out_proc_data(), но они считаются еще используемыми ******************************************************************************/ uint32_t usr_out_proc_data(uint32_t* data, uint32_t size) { /* если есть свободные дескрипторы на передачу по HDMA - ставим блок на передачу. Иначе возвращаем 0, чтобы на обработку этих данных функцию вызвали бы позже */ ++streams_cnt[2]; if (sport_tx_req_rdy()) { /* за один раз можем передать в SPORT не более SPORT_TX_REQ_SIZE_MAX слов */ if (size > SPORT_TX_REQ_SIZE_MAX) size = SPORT_TX_REQ_SIZE_MAX; sport_tx_start_req(data, size); return size; } return 0; } /****************************************************************************//** @brief Обработка завершения передачи по HostDMA Функция вызывается из обработчика прерывания, когда завершилась передача блока данных по HDMA в ПК, поставленного до этого на передачу с помощью hdma_send_req_start(). @param[in] addr Адрес слова, сразу за последним переданным словом @param[in] size Размер переданных данных в 32-битных словах ****************************************************************************/ void hdma_send_done(uint32_t* addr, uint32_t size) { ++streams_cnt[3]; stream_in_buf_free(size); } /***************************************************************************//** @brief Обработка завершения передачи по SPORT Функция вызывается из обработчика прерывания при завершении передачи блока данных по SPORT'у на цифровые выходы/ЦАП, поставленного до этого на передачу с помощью sport_tx_start_req(). @param[in] addr Адрес слова, сразу за последним переданным словом @param[in] size Размер переданных данных в 32-битных словах */ void sport_tx_done(uint32_t* addr, uint32_t size) { ++streams_cnt[1]; stream_out_buf_free(size); } /****************************************************************************//** @brief Обработка пользовательских команд. Функция вызывается при приеме команды от ПК с кодом большим или равным #L502_BF_CMD_CODE_USER. По завершению обработки необходимо обязательно вызвать l502_cmd_done(), указав код завершения команды и при необходимости передать данные с результатом @param[in] cmd Структура с описанием принятой команды ******************************************************************************/ void usr_cmd_process(t_l502_bf_cmd *cmd) { switch (cmd->code){ /* Command template case 0x800?:{ l502_cmd_done(rcv_code, rcv_data, rcv_data_length); //void l502_cmd_done (int32_t result, uint32_t *data, uint32_t size) break; } */ // typedef struct { // uint16_t code; /**< Код команды из #t_l502_bf_cmd_code */ // uint16_t status; /**< Статус выполнения - в обработчике не изменяется */ // uint32_t param; /**< Параметр команды */ // int32_t result; /**< Код результата выполнения команды */ // uint32_t data_size; /**< Количество данных, переданных с командой или возвращенных с ответом в 32-битных словах */ // uint32_t data[L502_BF_CMD_DATA_SIZE_MAX]; /**< Данные, передаваемые с командой и/или в качестве результата */ // } t_l502_bf_cmd; case 0x8001:{ //L502_BF_USR_CMD_CODE_ECHO l502_cmd_done(cmd-> param, NULL, 0); break; } case 0x8002:{ //L502_BF_USR_CMD_CODE_DATA_ECHO uint32_t rcv_data[cmd->data_size]; for (uint32_t I = 0; I < (cmd -> data_size); ++I){ //rcv_data[I] = (cmd-> data)[I]; rcv_data[I] = I; } l502_cmd_done(cmd-> param, rcv_data, cmd->data_size); break; } case 0x8003:{ //configure ADC uint32_t err_codes[15] = {0,}; err_codes[0] = params_set_lch_cnt(1); //err_codes[1] = params_set_lch(1, 1, L502_LCH_MODE_COMM, L502_ADC_RANGE_5, 1, 0);// chan index 1, chan 1, mode L502_LCH_MODE_COMM (=1),range L502_ADC_RANGE_5 (=1), avg, flags err_codes[1] = params_set_lch(0, 0, L502_LCH_MODE_COMM, L502_ADC_RANGE_5, 1, 0);// chan index 1, chan 1, mode L502_LCH_MODE_COMM (=1),range L502_ADC_RANGE_5 (=1), avg, flags err_codes[2] = params_set_adc_freq_div(1); err_codes[3] = params_set_ref_freq(2000000); err_codes[4] = params_set_adc_interframe_delay(0); err_codes[5] = params_set_sync_mode (L502_SYNC_INTERNAL); err_codes[6] = params_set_sync_start_mode (L502_SYNC_INTERNAL); //err_codes[7] = params_set_din_freq_div; //err_codes[8] = params_set_dac_freq_div; err_codes[9] = sport_in_set_step_size(1024); //L502_BF_PARAM_ADC_COEF //err_codes[10] = fpga_reg_write(f_regaddr_k[range], ??); //err_codes[11] = fpga_reg_write(f_regaddr_offs[range], ??); err_codes[12] = configure(); uint32_t err_codes_sum = 0; for (int i = 0; i < 15; ++i){ err_codes_sum += err_codes[i]; } l502_cmd_done(err_codes_sum, err_codes, 15); break; } case 0x8004:{ //start streams uint32_t err_codes[5] = {0,}; l502_stream_init(); err_codes[0] = stream_enable(L502_STREAM_ADC | L502_STREAM_DIN); //bitmask err_codes[1] = stream_out_preload(); err_codes[2] = streams_start(); //hdma_send_start(); l502_cmd_done(0, err_codes, 5); break; } case 0x8005:{ //get some data from adc buff. Or simple flag, raised inside usr_in_proc_data() uint32_t streams_sum = streams_cnt[0] + streams_cnt[1] + streams_cnt[2] + streams_cnt[3]; l502_cmd_done(streams_sum, streams_cnt, 4); break; } case 0x8006:{ //get data from SPORT_RX copied arr uint32_t sport_rx_nonzero_sum = 0; for (int i = 0; i < dbg_sport_rx_copy_size; ++i){ if (dbg_sport_rx_copy[i]){ ++sport_rx_nonzero_sum; } } l502_cmd_done(sport_rx_nonzero_sum, dbg_sport_rx_copy, 1024); break; } case 0x8007:{ //start data processing: No dataprocessing. Just copy data to output buffer TX_buff_I = 0; Proc_state.mode = TRANSPARENT; Proc_state.mode_next = TRANSPARENT; Proc_state.LFSM_state = 0; Proc_state.average_N_max = 10; // Proc_state.average_N_max = cmd->param; Proc_state.average_N = 1; Proc_state.TX_buff_I = 0; Proc_state.TX_buff_state = 0; Proc_state.AVG_buff_I = 0; Proc_state.AVG_buff_state = 0; Proc_state.FFT_buff_I = 0; Proc_state.FFT_buff_state = 0; Proc_state.digital_word_prev = 0; Proc_state.digital_word_curr = 0; for (uint32_t i = 0; i < TX_BUFF_SIZE; ++i){ TX_buff[i] = 0; } // l502_cmd_done(cmd-> param, NULL, 0); l502_cmd_done(TX_buff_I, NULL, 0); break; } case 0x8008:{ //get data from SPORT_RX copied arr TX_buff_I = 0; Proc_state.mode = AVG; Proc_state.mode_next = AVG; Proc_state.LFSM_state = 0; Proc_state.average_N_max = 10; // Proc_state.average_N_max = cmd->param; Proc_state.average_N = 1; Proc_state.TX_buff_I = 0; Proc_state.TX_buff_state = 0; Proc_state.AVG_buff_I = 0; Proc_state.AVG_buff_state = 0; Proc_state.FFT_buff_I = 0; Proc_state.FFT_buff_state = 0; Proc_state.digital_word_prev = 0; Proc_state.digital_word_curr = 0; for (uint32_t i = 0; i < TX_BUFF_SIZE; ++i){ TX_buff[i] = 0; } // l502_cmd_done(cmd-> param, NULL, 0); l502_cmd_done(TX_buff_I, NULL, 0); break; } case 0x8009:{ //request TX_buff_I_shadow value (last size of TX_buff transferred to pc ) l502_cmd_done(TX_buff_I_shadow, NULL, 0); break; } case 0x800A:{ //get data from SPORT_RX copied arr l502_cmd_done(cmd-> param, NULL, 0); break; } case 0x8010:{ //L502_BF_USR_CMD_CODE_ECHO //uint32_t test_res = f_sport_test(); l502_cmd_done(cmd-> param, NULL, 0); break; } /* case 0x8002:{ cmd-> result = cmd->param * 2; uint32_t data[] = {0,1,2,3,4,5,6,5,4,3,2,1,0}; l502_cmd_done(cmd-> param*3, data, 13); break;} case 0x8001:{ //cmd-> result = cmd->param * 2; uint32_t data[] = {6,5,4,3,2,1,0,1,2,3,4,5,6}; l502_cmd_done(cmd-> param*75, data, 13); break;} */ default: { l502_cmd_done(1, NULL, 0); } } //l502_cmd_done(1, 1, 1); //l502_cmd_done(L502_BF_ERR_UNSUP_CMD, NULL, 0); } /** @} */