#include "ltrsrv_mspec_ltr34.h"
#include "ltrsrv_log.h"

#define LTR34_SEND_FIFO_SIZE   (2UL*1024*1024-1)

#define LTR34_CMD_STATUS_MSK       (LTR_CRATE_STREAM_CMD_Msk | 0x30E0)
#define LTR34_CMD_STATUS_PERIOD    (LTR_CRATE_STREAM_CMD_INSTR | 0x00)
#define LTR34_CMD_STATUS_ECHO      (LTR_CRATE_STREAM_CMD_INSTR | 0x20)

#define LTR34_CMD_STATUS_BIT_EMPTY  0x10
#define LTR34_CMD_STATUS_BIT_FULL   0x01

static int f_proc_snd(t_ltr_crate* crate, t_ltr_module* module, uint32_t wrd) {
    /* по сбросу считаем, что очередь свободна и сбрасываем флаги переполнений */
    if ((wrd & LTR_CRATE_STREAM_CMD_Msk)==LTR_CRATE_STREAM_CMD_RESET) {
        module->stat.hard_send_fifo_full = 0;
        module->stat.hard_send_fifo_underrun=0;
        module->stat.hard_send_fifo_overrun=0;
    } else if ((wrd & LTR_CRATE_STREAM_TYPE_Msk)==LTR_CRATE_STREAM_TYPE_DATA) {
        /* отсчитываем количество переданных слов */
        module->stat.hard_send_fifo_full++;
    }
    return 0;
}




static int f_proc_rcv_cmd(t_ltr_crate* crate, t_ltr_module* module, uint32_t wrd) {
    int proc = 0;
    if (((wrd & LTR34_CMD_STATUS_MSK)==LTR34_CMD_STATUS_ECHO)||
            ((wrd & LTR34_CMD_STATUS_MSK)==LTR34_CMD_STATUS_PERIOD)) {
        /* анализ битов empty/full для проверки переполнения или голодания
           очереди */
        if (wrd & LTR34_CMD_STATUS_BIT_EMPTY) {
            if (!module->stat.hard_send_fifo_underrun)
                ltrsrv_log_rec(LTRSRV_LOGLVL_WARN, module->log_str, 0, "fifo first underrun");
            module->stat.hard_send_fifo_underrun=1;
        }

        if (wrd & LTR34_CMD_STATUS_BIT_FULL) {
            if (!module->stat.hard_send_fifo_overrun)
                ltrsrv_log_rec(LTRSRV_LOGLVL_WARN, module->log_str, 0, "fifo first overrun");
            module->stat.hard_send_fifo_overrun=1;
        }

        if (module->stat.hard_send_fifo_full==module->stat.hard_send_fifo_size) {
            ltr_crate_wait_send_rdy(crate);
        }

        if ((wrd & LTR34_CMD_STATUS_MSK)==LTR34_CMD_STATUS_ECHO) {
            /* эхо приходит на каждый семпл - используем для определения,
               что одно слово обработано и место освободилось */
            if (module->stat.hard_send_fifo_full)
                module->stat.hard_send_fifo_full--;
        } else {
             /* периодическое состояние приходит на каждые 1024 семплов.
               эти команды обрабатываем внутри сервера, не выдавая наружу */
            if (module->stat.hard_send_fifo_full < 1024) {
                module->stat.hard_send_fifo_full = 0;
            } else {
                module->stat.hard_send_fifo_full-=1024;
            }
            module->stat.hard_send_fifo_internal = ((wrd >> 16) & 0xFFF) << 10;
            proc = 1;
        }

    }
    return proc;
}






int ltrsrv_ltr34_init(t_ltr_module *module) {
    module->flags = LTR_MODULE_FLAGS_USE_SND_FIFO_STATUS | LTR_MODULE_FLAGS_HIGH_BAUD;
    module->stat.hard_send_fifo_size = LTR34_SEND_FIFO_SIZE-256;
    module->stat.hard_send_fifo_full = 0;
    module->func.proc_snd = f_proc_snd;
    module->func.proc_rcv_cmd = f_proc_rcv_cmd;
    return 0;
}




