#ifndef E502TSTP_H #define E502TSTP_H #include "x502api.h" #include #ifdef __cplusplus extern "C" { #endif /** @addtogroup tstpfunc_list Функции для работы с метками времени @{ **/ /***************************************************************************//** @addtogroup tstptype_list Константы и перечисления @{ *****************************************************************************/ #define TSP_NSEC_PER_SEC (1000000000) #define TSP_WRD1_SSEC_LEN (24) #define TSP_WRD2_SSEC_LEN (7) #define TSP_WRD2_SEC_LEN (19) #define TSP_WRD3_SEC_LEN (13) #define TSP_SSEC_WIDTH (31) #define TSP_WRD_NUM(wrd) (((wrd) >> 26) & 3) #define TSP_WRD0_ADC_CLK_NUM_MASK (0x3ffffff) #define TSP_WRD1_LOCK_MASK (1 << 25) #define TSP_WRD1_FMARK_MASK (1 << 24) #define TSP_WRD1_SSEC_MASK ((1 << TSP_WRD1_SSEC_LEN) - 1) #define TSP_WRD2_SEC_MASK (0x3ffff80) #define TSP_WRD2_SSEC_MASK ((1 << TSP_WRD2_SSEC_LEN) - 1) #define TSP_WRD2_SECSSEC_MASK ((1 << (TSP_WRD2_SEC_LEN + TSP_WRD2_SSEC_LEN)) - 1) #define TSP_WRD3_SEC_MASK ((1 << TSP_WRD3_SEC_LEN) - 1) #define TSP_WRD1_IS_FMARK(wrd) (!!((wrd) & TSP_WRD1_FMARK_MASK)) #define TSP_WRD1_IS_LOCK(wrd) (!!((wrd) & TSP_WRD1_LOCK_MASK)) #define TSP_WRD1_GET_SSEC(wrd) ((wrd) & TSP_WRD1_SSEC_MASK) #define TSP_WRD2_GET_SECSSEC(wrd) ((uint64_t)((wrd) & TSP_WRD2_SECSSEC_MASK) << TSP_WRD1_SSEC_LEN) #define TSP_WRD2_GET_SSEC(wrd) ((wrd) & TSP_WRD2_SSEC_MASK) #define TSP_WRD3_GET_SEC(wrd) ((uint64_t)((wrd) & TSP_WRD3_SEC_MASK) << (TSP_WRD1_SSEC_LEN + TSP_WRD2_SSEC_LEN + TSP_WRD2_SEC_LEN)) #define SSEC_MAX (0x7fffffff) #define TSTP_SSEC_TO_NSEC(time) (time > 0 ? ((uint32_t)((((double)((time) & SSEC_MAX)) / (1U << TSP_SSEC_WIDTH)) * TSP_NSEC_PER_SEC)) : ((uint32_t)((((double)((time*(-1)) & SSEC_MAX)) / (1U << TSP_SSEC_WIDTH)) * TSP_NSEC_PER_SEC))) #define TSTP_SECSSEC_TO_SEC(time) (time > 0 ? (uint32_t)((time) >> TSP_SSEC_WIDTH) : (uint32_t)((time * -1) >> TSP_SSEC_WIDTH)) #define TSTP_SECSSEC_TO_SEC_DOUBLE(time) (((double)(time)) / (1U << TSP_SSEC_WIDTH)) #define TSTP_SEC_TO_SSEC(time) (((uint64_t)(time)) << TSP_SSEC_WIDTH) /** Тип данных для хранения времени * Время хранится в секундах прошедшее с начала этой эпохи (00:00:00 UTC, 1 Января 1970 года) * Дробный формат хранения 32.31: 32 целых бит, 31 дробных бит, * старшие 32 бита - секунды, младшие 31 бит сабсекунды = 1 / (1<<31) секунд + сабсекунды, */ typedef uint64_t t_x502_tstptime; /** Структура для хранения контекста при обработке потока слов "на ввод" с включенными метками времени */ typedef struct { /** значение слов последней метки времени */ uint32_t wrd[4]; /** частота АЦП */ uint32_t adc_freq; /** частота DIN */ uint32_t din_freq; /** время первой метки времени */ t_x502_tstptime tstp_start_time; /** признак, что первая метка времени получена */ bool tstp_mark_rcvd; /** значение текущего обрабатываемого слова */ uint32_t cur_wrd; /** кол-во обработанных слов из потока */ uint32_t processed_wrds; /** кол-во слов АЦП после последней метки времени */ uint32_t adcwrds_after_tstp; /** кол-во слов DIN после последней метки времени */ uint32_t dinwrds_after_tstp; /** общее кол-во слов после последней метки времени */ uint32_t wrds_after_tstp; /** время последней метки времени */ t_x502_tstptime last_tstp_time; } t_x502_tstp_state; /** @} */ /***************************************************************************//** @addtogroup func_tstp Функции для работы с метками времени @{ *******************************************************************************/ /***************************************************************************//** @brief Инициализация tstp_state, в нем хранится текущий контекст для операций с метками времени из потока "на ввод" Данная функция инициализирует структуру в которой хранится контекст для работы с метками времени Необходимо указывать на частоту АЦП и DIN т.к. время для слов между двумя метками будет считаться в зависимости от частоты. @param[in] tstp_state Указатель на существующую струтуру t_x502_tstp_state @param[in] adc_freq Частота АЦП @param[in] din_freq Частота DIN *******************************************************************************/ X502_EXPORT(void) X502_tstp_init(t_x502_tstp_state *tstp_state, uint32_t adc_freq, uint32_t din_freq); /** @brief Обработать очередное слово wrd из потока "на ввод" * * Функция должна быть вызвана только один раз и последовательно для каждого слова полученного из X502_Recv * * @param[in] tstp_state Указатель на струтуру t_x502_tstp_state предварительно инициализированную через tstp_init() * @param[in] wrd Слово из потока "на ввод" */ X502_EXPORT(void) X502_tstp_process_wrd(t_x502_tstp_state *tstp_state, uint32_t wrd); /** @brief Узнать время текущего обработанного слова * * Узнать время текущего слова которое до этого было обработано функцией tstp_process_wrd() * Формат времени: 32бита - секунды, 31 бит сабсекунды = 1 / (1<<31) секунд * * @param[in] tstp_state Указатель на струтуру t_x502_tstp_state предварительно инициализированную через tstp_init() * @param[in] ret Указатель на t_x502_tstptime по которому будет сохранено расчитанное значение времени для текущего слова */ X502_EXPORT(void) X502_tstp_get_curwrd_time(t_x502_tstp_state *tstp_state, t_x502_tstptime *ret); /** @brief Возвращает признак того что часы синхронизированы * * Возвращает признак "захват PTP" для текущего обработанного слова * * @param[in] tstp_state Указатель на струтуру t_x502_tstp_state предварительно инициализированную через tstp_init() * * @return true: присутствует признак "захват PTP" для текущего обработанного слова, false: признак "захват PTP" отсутствует */ X502_EXPORT(bool) X502_tstp_get_lock(t_x502_tstp_state *tstp_state); /** @} */ /** @} */ #ifdef __cplusplus } #endif #endif //E502TSTP_H