#include #include "x502tstp.h" typedef enum { STREAM_IN_WRD_ADC = 0, STREAM_IN_WRD_DIN = 1, STREAM_IN_WRD_MSG = 2, STREAM_IN_WRD_USR = 3, STREAM_IN_WRD_TSP = 4, } t_stream_in_wrd_type; #define STREAM_IN_WRD_TYPE(wrd) wrd & 0x80000000 ? STREAM_IN_WRD_ADC : \ (wrd & 0xFF000000) == 0x0 ? STREAM_IN_WRD_DIN : \ (wrd & 0xF0000000) == 0x40000000 ? STREAM_IN_WRD_TSP : \ ((wrd & 0xFF000000)>>24) == 0x01 ? STREAM_IN_WRD_MSG : STREAM_IN_WRD_USR static uint64_t get_secssec(uint32_t wrd1, uint32_t wrd2, uint32_t wrd3) { uint64_t wrd1_sec = TSP_WRD1_GET_SSEC(wrd1); uint64_t wrd2_sec = TSP_WRD2_GET_SECSSEC(wrd2); uint64_t wrd3_sec = TSP_WRD3_GET_SEC(wrd3); uint64_t ret; ret = wrd1_sec | wrd2_sec | wrd3_sec; return ret; //return TSP_WRD3_GET_SEC(wrd3) | TSP_WRD2_GET_SECSSEC(wrd2) | TSP_WRD1_GET_SSEC(wrd1); } #if 0 static int32_t get_ssec(uint32_t wrd1, uint32_t wrd2, uint32_t wrd3) { int32_t ret; ret = (TSP_WRD2_GET_SSEC(wrd2) << TSP_WRD1_SSEC_LEN) | TSP_WRD1_GET_SSEC(wrd1); if(ret < 0) { fprintf(stderr, "unexpected get_ssec ret=%d\n", ret); while(1); } return ret; } static uint32_t get_sec(uint32_t wrd2) { return ((wrd2 & TSP_WRD2_SEC_MASK) >> TSP_WRD2_SSEC_LEN); } #endif X502_EXPORT(bool) X502_tstp_get_lock(t_x502_tstp_state *tstp_state) { if (TSP_WRD1_IS_LOCK(tstp_state->wrd[1])) { return true; } else { return false; } } X502_EXPORT(void) X502_tstp_process_wrd(t_x502_tstp_state *tstp_state, uint32_t wrd) { t_stream_in_wrd_type type = STREAM_IN_WRD_TYPE(wrd); if (type == STREAM_IN_WRD_TSP) { if (TSP_WRD_NUM(wrd) == 3) { uint64_t cur_tspt_time; tstp_state->wrd[3] = wrd; cur_tspt_time = get_secssec(tstp_state->wrd[1], tstp_state->wrd[2], tstp_state->wrd[3]); if (TSP_WRD1_IS_FMARK(tstp_state->wrd[1])) { tstp_state->tstp_start_time = cur_tspt_time; #ifdef DEBUG if (tstp_state->tstp_mark_rcvd) { fprintf(stderr, "fmark && tstp_mark_rcv unexpected!\n"); } #endif tstp_state->tstp_mark_rcvd = true; } tstp_state->adcwrds_after_tstp = 0; tstp_state->dinwrds_after_tstp = 0; tstp_state->wrds_after_tstp = 0; if (cur_tspt_time < tstp_state->last_tstp_time) { #ifdef DEBUG fprintf(stderr, "cur = %" PRIu64 " last = %" PRIu64 "\n", cur_tspt_time, tstp_state->last_tstp_time); fprintf(stderr, "cur_tstp < last_tstp unexpected!\n"); #endif return; } //printf("tstp time = %d.%09d\n", TSTP_SECSSEC_TO_SEC(cur_tspt_time), TSTP_SSEC_TO_NSEC(cur_tspt_time)); tstp_state->last_tstp_time = cur_tspt_time; } else { if (TSP_WRD_NUM(wrd) == 0) { tstp_state->wrd[0] = wrd; } else if (TSP_WRD_NUM(wrd) == 1) { tstp_state->wrd[1] = wrd; } else if (TSP_WRD_NUM(wrd) == 2) { tstp_state->wrd[2] = wrd; } tstp_state->wrds_after_tstp++; } } else { if (type == STREAM_IN_WRD_DIN) { tstp_state->dinwrds_after_tstp++; } else if (type == STREAM_IN_WRD_ADC) { tstp_state->adcwrds_after_tstp++; } tstp_state->wrds_after_tstp++; } tstp_state->processed_wrds++; tstp_state->cur_wrd = wrd; } X502_EXPORT(void) X502_tstp_init(t_x502_tstp_state *tstp_state, uint32_t adc_freq, uint32_t din_freq) { memset(tstp_state, 0, sizeof(*tstp_state)); tstp_state->adc_freq = adc_freq; tstp_state->din_freq = din_freq; } X502_EXPORT(void) X502_tstp_get_curwrd_time(t_x502_tstp_state *tstp_state, t_x502_tstptime *ret) { t_x502_tstptime wrd_time; t_stream_in_wrd_type type = STREAM_IN_WRD_TYPE(tstp_state->cur_wrd); if (type == STREAM_IN_WRD_DIN) { wrd_time = tstp_state->last_tstp_time + ((double)(tstp_state->dinwrds_after_tstp - 1) / tstp_state->din_freq) * (1U << 31); } else if (type == STREAM_IN_WRD_ADC) { wrd_time = tstp_state->last_tstp_time + ((double)(tstp_state->adcwrds_after_tstp - 1)/ tstp_state->adc_freq) * (1U << 31); } else { // чтобы посчитать время слова отличного от АЦП и DIN нужно знать частоту их появления wrd_time = tstp_state->last_tstp_time + ((double)(tstp_state->adcwrds_after_tstp - 1)/ tstp_state->adc_freq) * (1U << 31); wrd_time += tstp_state->last_tstp_time + ((double)(tstp_state->dinwrds_after_tstp - 1) / tstp_state->din_freq) * (1U << 31); } if (ret) { *ret = wrd_time; } }