using System;
using ltrModulesNet;


/* Данный пример демонстрирует работу с модулем LTR114 из программы на языке C#.
 * Пример представляет собой консольную программу, которая устанавливает связь с модулем,
 * выводит информацию о модуле, устанавливает настройки и собирает заданное кол-во 
 * блоков заданного размера, выводя на экран только по первому значению для каждого канала.
 * 
 * Необходимо установить номер слота, в котором вставлен модуль (константа SLOT).
 * Настройки сбора задаются в коде при конфигурации модуля.
 */


namespace ltr114_console
{
    class ltr114_console
    {
         /* Номер слота в крейте, где вставлен модуль */
        const int SLOT = 13;
        /* Количество отсчетов на канал, принмаемых за раз */
        const int RECV_BLOCK_CH_SIZE = 256;
        /* Количество блоков, которые нужно принять и выйти */
        const int RECV_BLOCK_CNT = 50;
        /* Таймаут на ожидание данных при приеме (без учета времени преобразования) */
        const int RECV_TOUT = 4000;


        static int Main(string[] args)
        {          
            /* LTR11_Init() вызывается уже в конструкторе */
            ltr114api hltr114 = new ltr114api();
            /* отрываем модуль. Используем упрощенный вариант функции с указанием только слота.
             * (есть вариант как с только со слотом, так и с серийным крейта и слотом 
             *  + полный) */
            _LTRNative.LTRERROR err = hltr114.Open(SLOT);
            if (err != _LTRNative.LTRERROR.OK)
            {
                Console.WriteLine("Не удалось открыть модуль. Ошибка {0}: {1}",
                    err, ltr114api.GetErrorString(err));
            }
            else
            {
                /* получение информации о модуле из flash-памяти */
                err = hltr114.GetConfig();
                if (err != _LTRNative.LTRERROR.OK)
                {
                    Console.WriteLine("Не удалось прочитать информацию о модуле. Ошибка {0}: {1}",
                         err, ltr114api.GetErrorString(err));
                }
                else
                {
                    /* выводим информацию из hltr11.ModuleInfo */
                    Console.WriteLine("Информация о модуле: ");
                    Console.WriteLine("  Название модуля: {0}", hltr114.ModuleInfo.Name);
                    Console.WriteLine("  Серийный номер : {0}", hltr114.ModuleInfo.Serial);
                    Console.WriteLine("  Версия прошивки: {0}", hltr114.ModuleInfo.VerMCUStr);
       
                    /* --------------- задание параметров работы модуля ------------ */
                    /* Устанавливаем частоту АЦП - функция подбора делителя
                     * в Net сразу заполняет настройку делителя */
                    hltr114.FindFreqDivider(4000);
                    /* Количество опрашиваемых каналов */
                    hltr114.LChQnt = 3;

                    /* заполняем последовательность логических каналов */
                    /* первый канал, измерение напряжения, диапазон +/-10 В */
                    hltr114.SetLChannel(0, 0, ltr114api.MeasModes.U, ltr114api.Ranges.U_10);
                    /* второй канал, измерение сопротивления, диапазон 1200 Ом */
                    hltr114.SetLChannel(1, 1, ltr114api.MeasModes.R, ltr114api.Ranges.R_1200);
                    /* третий канал, измерение напряжения, диапазон +/-0.4 В */
                    hltr114.SetLChannel(2, 2, ltr114api.MeasModes.U, ltr114api.Ranges.U_04);

                    /* внутренняя синхронизация */
                    hltr114.SyncMode = ltr114api.SyncModes.Internal;
                    /* без межкадровой задержки */
                    hltr114.Interval = 0;

                    err = hltr114.SetADC();
                    if (err != _LTRNative.LTRERROR.OK)
                    {
                        Console.WriteLine("Не удалось установить настройки модуля. Ошибка {0}: {1}",
                             err, ltr114api.GetErrorString(err));
                    }
                    else 
                    {
                        Console.WriteLine("Настройки модуля выполнены успешно. Частота АЦП {0} Гц, на канал {1} Гц",
                               hltr114.AdcFreq, hltr114.ChFreq);
                    }
                }

                if (err == _LTRNative.LTRERROR.OK) 
                {
                    err = hltr114.Calibrate();
                    if (err != _LTRNative.LTRERROR.OK)
                    {
                        Console.WriteLine("Не удалось выполнить начальную калибровку модуля. Ошибка {0}: {1}",
                            err, ltr114api.GetErrorString(err));
                    }
                    else
                    {
                        Console.WriteLine("Начальная калибровка выполнена успешно!");
                    }
                }


                if (err == _LTRNative.LTRERROR.OK)
                {
                    int recv_data_cnt = RECV_BLOCK_CH_SIZE * hltr114.LChQnt;
                    /* для определения кол-ва слов, соответствующих нужному кол-ву кадров, используем
                     * свойство FrameLength */
                    int recv_words_cnt = RECV_BLOCK_CH_SIZE * hltr114.FrameLength; 

                    uint[] rbuf = new uint[recv_words_cnt];
                    double[] data = new double[recv_data_cnt];

                    /* запуск сбора данных */
                    err = hltr114.Start();
                    if (err != _LTRNative.LTRERROR.OK)
                    {
                        Console.WriteLine("Не удалось запустить сбор данных. Ошибка {0}: {1}",
                             err, ltr114api.GetErrorString(err));
                    }
                    else
                    {
                        _LTRNative.LTRERROR stop_err;
                        for (int i = 0; (i < RECV_BLOCK_CNT) &&
                                (err == _LTRNative.LTRERROR.OK); i++)
                        {
                            int rcv_cnt;
                            /* в таймауте учитываем время выполнения самого преобразования*/
                            uint tout = RECV_TOUT + (uint)(RECV_BLOCK_CH_SIZE / hltr114.ChFreq + 1);
                            /* прием необработанных слов. есть варинант с tmark и без него для удобства */
                            rcv_cnt = hltr114.Recv(rbuf, (uint)rbuf.Length, tout);

                            /* значение меньше 0 => код ошибки */
                            if (rcv_cnt < 0)
                            {
                                err = (_LTRNative.LTRERROR)rcv_cnt;
                                Console.WriteLine("Ошибка приема данных. Ошибка {0}: {1}",
                                                  err, ltr114api.GetErrorString(err));
                            }
                            else if (rcv_cnt != rbuf.Length)
                            {
                                err = _LTRNative.LTRERROR.ERROR_RECV_INSUFFICIENT_DATA;
                                Console.WriteLine("Приняли недостаточно данных: запрашивали {0}, приняли {1}",
                                                  rbuf.Length, rcv_cnt);
                            }
                            else
                            {
                                /* перевод значений в физические величины */
                                err = hltr114.ProcessData(rbuf, data, ref rcv_cnt,
                                    ltr114api.CorrectionModes.Init,
                                    ltr114api.ProcFlags.Value);

                                if (err != _LTRNative.LTRERROR.OK)
                                {
                                    Console.WriteLine("Ошибка обработки данных. Ошибка {0}: {1}",
                                                       err, ltr11api.GetErrorString(err));
                                }
                                else
                                {
                                    /* при успешной обработке для примера выводим по одному значению
                                     * для каждого канала */
                                    Console.Write("Блок {0}.", i + 1);
                                    for (int ch = 0; ch < hltr114.LChQnt; ch++)
                                    {
                                        /* если все ок - выводим значение (для примера только первое) */
                                        Console.Write(" {1}", ch + 1, data[ch].ToString("F7"));
                                        if (ch == (hltr114.LChQnt - 1))
                                            Console.WriteLine("");
                                        else
                                            Console.Write(", ");
                                    }
                                }
                            }
                        }

                        /* останавливаем сбор данных */
                        stop_err = hltr114.Stop();
                        if (stop_err != _LTRNative.LTRERROR.OK)
                        {
                            Console.WriteLine("Не удалось остановить сбор данных. Ошибка {0}: {1}",
                                 stop_err, ltr11api.GetErrorString(stop_err));
                            if (err == _LTRNative.LTRERROR.OK)
                                err = stop_err;
                        }
                    }
                }
            }

            /* закрываем соединение */
            if (hltr114.IsOpened() == _LTRNative.LTRERROR.OK)
                hltr114.Close();

            return (int)err;
        }
    }
}
