Files
E502_ADC_BFfirmware/src/l502_user_process.c

750 lines
23 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.

/***************************************************************************//**
@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 <stdlib.h>
#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);
}
/** @} */