Общий подход к использованию интерфейсных функций{#sect_gen_descr}
==============================================================

  Общий алгоритм работы с модулем{#sect_gen_alg}
  ==============================================================

Данный раздел описывает типичную последовательность действий при работе с модулем LTR210. Более подробно каждый шаг будет описан в последующих разделах.

Типичная последовательность действий имеет следующий вид:
1. Создать экземпляр структуры TLTR210, представляющей собой описатель модуля. Описатель модуля содержит всю информацию о модуле и используется при вызове всех остальных функций.
2. Проинициализировать поля описателя с помощью LTR210_Init()
3. Установить соединение с интересующим модулем с помощью функции LTR210_Open().
4. Проверить, загружена ли прошивка ПЛИС модуля, с помощью функции LTR210_FPGAIsLoaded(). Если прошивка не загружена, то загрузить ее, вызвав функцию LTR210_LoadFPGA().
5. Заполнить необходимые поля с настройками модуля подструктуры [Cfg](@ref TLTR210::Cfg) [описателя модуля](@ref TLTR210) и вызвать LTR210_SetADC(), для записи настроек в модуль.
6. При желании можно выполнить измерение собственного нуля для дополнительной коррекции его ухода с помощью LTR210_MeasAdcZeroOffset().
6. Запуск сбора данных с помощью LTR210_Start().
7. Прием и обработка данных в зависимости от режима, как описано ниже
8. По завершению работы выполнить останов сбора данных с помощью LTR210_Stop().
9. Закрыть соединение с модулем, вызвав функцию LTR210_Close().
 
 
 Работа с модулем в режиме покадрового сбора{#sect_gen_alg_frame_mode}
 ----------------------------------------------------------
 Типичный цикл приема и обработки данных в режиме покадрового сбора, выглядит следующим образом:
 1. Ожидание прихода данных от модуля с помощью LTR210_WaitEvent(). 
 2. По типу события (параметр event) определить, что за данные пришли:
    - Если не пришло никаких данных за указанное время, то возвращаемся к пункту 1 для ожидания дальнейших данных. При включенной [периодической посылке статуса](@ref sect_gen_keepalive), можно проверить время прихода последнего статуса для выявления фактов нарушения работы модуля.
    - Если принят [периодический статус модуля (сигнал жизни)](@ref sect_gen_keepalive), проанализировать статус (при необходимости) и перейти к пункту 1.
    - Если принято начало записанного кадра, то переход к пункту 3
 3. Прием отсчетов кадра в количестве  [State.RecvFrameSize](@ref TLTR210_STATE::RecvFrameSize) с помощью LTR210_Recv().
 4. Обработка принятого кадра с помощью LTR210_ProcessData().
 5. Анализ [статуса принятого кадра](@ref sect_gen_frame_status), для определения, действителен ли принятый кадр. Пользовательская обработка и переход к пункту 1. 
 
 
 Работа с модулем при непрерывном потоковом вводе {#sect_gen_alg_stream_mode}
 --------------------------------------------------------------
Типичный цикл приема и обработки данных аналогичен большинству модулей АЦП и выглядит следующим образом:
1. Прием заданного количества отсчетов с помощью LTR210_Recv().
2. Обработка принятых отсчетов с помощью LTR210_ProcessData().






Загрузка прошивки ПЛИС модуля{#sect_gen_load_fpga}
==========================================

В модуле LTR210 не реализована возможность хранения прошивки ПЛИС во внутренней энергонезависимой памяти, поэтому для работы с модулем необходимо предварительно загрузить прошивку в ПЛИС. 

Загрузка прошивки в модуль является, как правило, самым первым действием, которое необходимо выполнить, после установления соединения с модулем через LTR210_Open(). Однако, так как после загрузки прошивки ПЛИС она сохраняется в модуле до сброса питания, прошивку не обязательно повторно загружать, если она уже была загружена при предыдущем сеансе работы с модулем. Для проверки, загружена ли прошивка, служит функция LTR210_FPGAIsLoaded(). Если эта функция вернула LTR_OK, то прошивка уже загружена и можно переходить к настройке модуля. В противном случае, нужно загрузить прошивку с помощью функции LTR210_LoadFPGA().

Функция LTR210_LoadFPGA() принимает одним из параметров имя файла прошивки. Файл <B> ltr210_fpga.rbf </B>, содержащий прошивку, поставляется вместе с библиотекой ltr210api. Кроме того, в ОС Windows последняя версия прошивки на момент создания библиотеки встраивается в библиотеку как ресурс, что позволяет не хранить отдельно файл прошивки. Загрузка встроенной в библиотеку прошивки выполняется при передаче пустой строки или нулевого указателя в качестве имени файла. Для ОС Linux при установке из предоставляемых пакетов, файл прошивки устанавливается в директорию <B> /usr/share/ltrapi/ltr210 </B> и при указании пустого имени берется файл, расположенный по этому стандартному пути.


Следует отметить, что в LTR210_LoadFPGA() можно передать указатель на функцию обратного вызова (callback), которая будет вызваться каждый раз, когда был успешно записан блок данных из файла прошивки в ПЛИС. Это позволяет при необходимости реализовать в программе индикатор прогресса загрузки. В функцию обратного вызова каждый раз передаются полный размер файла прошивки в байтах, количество успешно записанных байт и указатель на пользовательские данные, который можно передать в LTR210_LoadFPGA(). В первый раз функция обратного вызова будет вызвана сразу после успешного открытия файла (или загрузки ресурса) с нулевым размером записанных байт, а последний --- после успешного завершения загрузки --- с размером записанных байт равным размеру прошивки. В случае возникновения ошибки LTR210_LoadFPGA() немедленно возвращает код произошедшей ошибки в качестве результата, не вызывая при этом дополнительно функцию обратного вызова. Если индикатор загрузки не требуется, то в качестве указателя на функцию можно передать 
нулевой указатель.


Настройка модуля{#sect_gen_cfg}
=============================================================
Если прошивка ПЛИС была загружена, то следующим этапом необходимо установить настройки модуля.

Настройка модуля выполняется аналогично большинству других модулей LTR: вначале значения всех параметров модуля записываются в соответствующие поля [структуры описателя модуля](@ref TLTR210), затем вызывается функция LTR210_SetADC(), которая значения этих полей передает модулю.

Следует отметить, что все поля, относящиеся к настройке модуля, объединены в структуру типа #TLTR210_CONFIG (поле  [Cfg](@ref TLTR210::Cfg) [описателя модуля](@ref TLTR210)). Только эти поля пользователь должен изменять вручную в [описателе модуля](@ref TLTR210) при штатной работе и только эти поля влияют на параметры, записываемые LTR210_SetADC().

При настройке модуля задаются следующие параметры:
- Частота сбора АЦП (раздел @ref sect_gen_cfg_adc_freq)
- Настройки каналов АЦП (раздел @ref sect_gen_cfg_adc_ch)
- Размер кадра и предыстории для режима покадрового сбора (раздел @ref sect_gen_cfg_frame)
- Событие синхронизации, по которому происходит сбор кадра (раздел @ref sect_gen_cfg_sync)
- Настройки для работы цепочки модулей LTR210 в группе (раздел @ref sect_gen_cfg_group)

После выполнения LTR210_SetADC() рассчитываются некоторые параметры, которые являются производными от настроек из #TLTR210_CONFIG. Эти параметры записываются в соответствующие поля структуры состояния модуля типа #TLTR210_STATE (поле [ State](@ref TLTR210::State) [описателя модуля](@ref TLTR210)). Например, на основе делителей частоты АЦП и коэффициента прореживания рассчитывается результирующая частота сбора АЦП в Гц и записывается в поле [AdcFreq](@ref TLTR210_STATE::AdcFreq).


Настройка модуля должна быть выполнена хотя бы один раз перед началом записи данных. 

Кроме того, часть параметров модуля может быть изменена при запущенном сборе:
- Диапазоны измерения каналов АЦП
- Режим измерения для каналов АЦП
- Уровень аналоговой синхронизации
- Частота кадров при периодическом сборе

Для изменения этих параметров на лету, нужно аналогичным образом изменить нужные поля [структуры конфигурации](@ref TLTR210::Cfg) и вызвать LTR210_SetADC().


Настройка частоты сбора АЦП{#sect_gen_cfg_adc_freq}
-----------------------------------------------------
Оба канала АЦП модуля всегда работают параллельно с одной и той же частотой преобразования, которая может достигать до 10 МГц (на каждый канал).

Частота сбора АЦП задается двумя параметрами:
- Делителем частоты преобразования АЦП. Частота 10 МГц делится на делитель, равный значению поля [AdcFreqDiv](@ref TLTR210_CONFIG::AdcFreqDiv)+1. Значение [AdcFreqDiv](@ref TLTR210_CONFIG::AdcFreqDiv) может быть от 0 до #LTR210_ADC_FREQ_DIV_MAX-1.
- Коэффициентом прореживания данных. Для получения более низких частот сбора в ПЛИС сделано прореживание данных от АЦП. Этот коэффициент задается полем [AdcDcmCnt](@ref TLTR210_CONFIG::AdcDcmCnt). Из [AdcDcmCnt](@ref TLTR210_CONFIG::AdcDcmCnt)+1 отсчетов будет записан в буфер модуля только один отсчет. Значение [AdcDcmCnt](@ref TLTR210_CONFIG::AdcDcmCnt) может изменяться в диапазоне от 0 до #LTR210_ADC_DCM_CNT_MAX-1.

Таким образом, результирующая частота сбора для каждого канала АЦП будет равна \f[ f_{acq} = \frac{10000000}{(AdcFreqDiv+1)*(AdcDcmCnt+1)} \text{ Гц}\f]

Для установки нужных значений полей [AdcFreqDiv](@ref TLTR210_CONFIG::AdcFreqDiv) и [AdcDcmCnt](@ref TLTR210_CONFIG::AdcDcmCnt) можно также воспользоваться функцией LTR210_FillAdcFreq(), которая подбирает эти значения так, чтобы частота сбора АЦП была наиболее близка к указанной в соответствующем параметре функции.

После вызова LTR210_SetADC() значение, соответствующее реально установленной частоте сбора АЦП, записывается в поле [AdcFreq](@ref TLTR210_STATE::AdcFreq) структуры [состояния модуля](@ref TLTR210::State).

Установленная частота сбора не зависит от количества разрешенных каналов АЦП.

Настройка каналов АЦП{#sect_gen_cfg_adc_ch}
--------------------------------------------------
Каждый модуль LTR210 имеет два канала, которые выполняют преобразования параллельно. Можно разрешить запись как по любому из двух, так и по обоим каналам одновременно. Настройки каждого канала объединены в структуре #TLTR210_CHANNEL_CONFIG. Массив структур из 2-х элементов, каждый элемент которого соответствует нужному каналу, является полем [Ch](@ref TLTR210_CONFIG::Ch) структуры с [настройками модуля](@ref TLTR210::Cfg).

Для каждого канала можно независимо задать:
 - Разрешена ли запись по этому каналу. Задается полем [Enabled](@ref TLTR210_CHANNEL_CONFIG::Enabled).
 - Диапазон для данного канала (поле [Range](@ref TLTR210_CHANNEL_CONFIG::Range)).
 - Режим работы канала (поле [Mode](@ref TLTR210_CHANNEL_CONFIG::Mode)): открытый вход (без отсечки постоянной составляющей), закрытый вход (с отсечкой постоянной составляющей) или измерение собственного нуля.
 - Верхний и нижний уровень синхронизации при использовании соответствющего режима синхронизации (раздел @ref sect_gen_cfg_sync)
 - Режим работы специального бита, вставляемого в поток отсчетов, соответствующих данному каналу (раздел @ref sect_dig_bit_mode).

Настройка параметров принимаемого кадра{#sect_gen_cfg_frame}
------------------------------------------------------
В режиме покадрового сбора, который является основным для модуля LTR210, выдача отсчетов осуществляется блоками, называемыми в данном документе кадрами. Выдача кадра осуществляется только при возникновении события синхронизации. 

Количество точек в кадре на канал задается с помощью поля [FrameSize](@ref TLTR210_CONFIG::FrameSize). При этом часть отсчетов кадра соответствует измерениям непосредственно перед возникновением события синхронизации, а часть --- отсчетам АЦП непосредственно после его возникновения. Отсчеты кадра, соответствующие времени до события, приведшего к выдачи этого кадра, называются предысторией события. Размер предыстории в количестве точек на канал задается с помощью параметра [HistSize](@ref TLTR210_CONFIG::HistSize) (может быть равен 0).

Ограничения на размер кадра в зависимости от режима записи описаны в разделе @ref sect_gen_frame_wr.

После последнего слова кадра всегда высылается [Статус кадра](@ref sect_gen_frame_status), который содержит информацию о действительности кадра, а также о различных других событиях, произошедших во время записи и выдачи кадра. Статус кадра всегда должен быть проверен, чтобы можно было сделать вывод о правильности принятых данных.

Таким образом, сам кадр состоит из \f$ N_{ch}*FrameSize + 1 \f$ слов, где \f$N_{ch}\f$ --- количество разрешенных каналов (1 или 2). После записи настроек модуля с помощью LTR210_SetADC() вычисленный размер кадра сохраняется в поле [RecvFrameSize](@ref TLTR210_STATE::RecvFrameSize) структуры [состояния модуля](@ref TLTR210::State). Значение этого поля можно использовать в дальнейшем при приеме данных от модуля.

Настройка события синхронизации{#sect_gen_cfg_sync}
------------------------------------------------------------------------------
В режиме покадрового сбора при вызове функции LTR210_Start() модуль переходит в режим ожидания заданного условия, и только при возникновении этого условия будет выдан кадр данных в интерфейс модуля. Это условие, называемое событием синхронизации, настраивается с помощью поля [SyncMode](@ref TLTR210_CONFIG::SyncMode). Само условие должно быть настроено до вызова LTR210_Start() на этапе конфигурации модуля.

Возможны следующие варианты события синхронизации:
- По команде, пришедшей от ПК. Эта команда посылается с помощью функции LTR210_FrameStart(). По приходу команды будет осуществлена выдача одного кадра данных.
- По фронту или спаду аналогового сигнала на одном из двух каналов относительно заданного уровня синхронизации. Уровень синхронизации задается отдельно для каждого канала с помощью двух уровней --- верхнего уровня гистерезиса (поле [SyncLevelH](@ref TLTR210_CHANNEL_CONFIG::SyncLevelH)) и нижнего (поле [SyncLevelL](@ref TLTR210_CHANNEL_CONFIG::SyncLevelL)). Два уровня позволяют избежать ложного срабатывания даже при зашумленном сигнале. Фронтом считается переход сигнала через верхний уровень, при условии, что до этого он был ниже нижнего уровня. Спадом же --- переход ниже нижнего уровня, если до этого сигнал превышал верхний. 
Установленные уровни должны быть в пределах, соответствующих установленному диапазону для данного канала. Безусловно, верхний уровень должен быть не ниже нижнего. При этом запись по каналу, используемому для аналоговой синхронизации, может быть запрещена, если интересуют лишь данные другого канала, но диапазон и режим сбора должен быть настроен верно.
- По фронту или спаду цифрового сигнала на входе SYNC. Важно отметить, что этот режим предназначен для синхронизации от внешнего источника цифрового сигнала, отличного от другого модуля LTR210. Для работы нескольких модулей LTR210 в группе по принципу "Ведущий - ведомые" существует специальная [настройка для работы модуля в группе](@ref sect_gen_cfg_group).
- Периодический сбор кадров. В этом режиме событие синхронизации генерируется аппаратурой самого модуля с заданной частотой. Эта частота определяется полем [FrameFreqDiv](@ref TLTR210_CONFIG::FrameFreqDiv) и равняется \f$ f_{frame} = \frac{10^6}{FrameFreqDiv + 1}\f$ Гц. После вызова LTR210_SetADC() рассчитанное значение этой частоты в Герцах записывается в поле [FrameFreq](@ref TLTR210_STATE::FrameFreq) структуры [состояния модуля](@ref TLTR210::State). Для заполнения поля [FrameFreqDiv](@ref TLTR210_CONFIG::FrameFreqDiv) можно также использовать функцию LTR210_FillFrameFreq().

Следует отметить, что если после возникновения события синхронизации и до завершения записи и последующей выдачи в интерфейс кадра произойдет еще одно событие синхронизации, то это событие будет отброшено. Предыдущий кадр же будет успешно передан, но для оповещения о пропущенном событии в флагах его статуса будет установлен флаг #LTR210_STATUS_FLAG_SYNC_SKIP.

Отдельно следует отметить, что [SyncMode](@ref TLTR210_CONFIG::SyncMode)=#LTR210_SYNC_MODE_CONTINUOUS является специальным случаем. При данном значении модуль настраивается на режим непрерывного сбора, который более подробно описан в разделе @ref sect_gen_stream_mode.


Работа нескольких модулей LTR210 в группе{#sect_gen_cfg_group}
---------------------------------------------------

Для модуля LTR210 имеется возможность объединять несколько модулей в цепочку по принципу "Ведущий-ведомые". Для настройки данного режима предназначено поле [GroupMode](@ref TLTR210_CONFIG::GroupMode). По-умолчанию это поле равно #LTR210_GROUP_MODE_INDIVIDUAL, что соответствует работе модуля независимо от остальных.

При работе модулей в группе необходимо один модуль настроить ведущим (мастером), установив [GroupMode](@ref TLTR210_CONFIG::GroupMode) = #LTR210_GROUP_MODE_MASTER. Ведущий модуль при запуске записи отслеживает события синхронизации в соответствии с установленным значением поля [SyncMode](@ref TLTR210_CONFIG::SyncMode). При обнаружении события синхронизации ведущий модуль не только выдает кадр в интерфейс с крейтом, но и генерирует импульс на линии SYNC. Для ведущего модуля может быть установлено любое значение [SyncMode](@ref TLTR210_CONFIG::SyncMode), кроме #LTR210_SYNC_MODE_CONTINUOUS.

Ведомые модули должны по цепочке быть соединены с ведущем с помощью входов SYNC (подробнее описано в документе [\"Крейтовая система LTR. Руководство пользователя\"](http://www.lcard.ru/download/ltr.pdf)). Т.е. если имеется ведущий модуль <I>M</I> и два ведомых <I>S1</I> и <I>S2</I>, то M может быть соединен с <I>S1</I>, а <I>S1</I> с <I>S2</I>. Для всех ведомых модулей должно быть установлено поле [GroupMode](@ref TLTR210_CONFIG::GroupMode) = #LTR210_GROUP_MODE_SLAVE. При этом поле [SyncMode](@ref TLTR210_CONFIG::SyncMode) не имеет значения --- ведомый модуль всегда запускает сбор кадра по сигналу от ведущего. 

Модули могут быть настроены в произвольном порядке. Однако запуск записи данных через LTR210_Start() следует сперва выполнить для всех ведомых модулей, а уже только после этого для ведущего, чтобы гарантировать, что первое событие синхронизации не будет потеряно ни одним ведомым.


Настройка скорости выдачи данных в интерфейс{#sect_gen_cfg_transf_rate}
-------------------------------------------------------------------
При возникновении события синхронизации записанные данные вычитываются из кольцевого буфера и передаются в интерфейс модуль \f$\to\f$ крейт с заданной скоростью. Максимальная скорость определяется типом крейта, в который вставлен модуль. Для LTR-U-1 она равна 200 КСлов/c, для остальных крейтов --- 500 КСлов/c. Эта скорость определяет время выдачи записываемого кадра и влияет на минимальный интервал следования событий синхронизации, которые не будут пропущены, а также на максимальный размер записываемого кадра в случае, если автоматическая приостановка записи не включена (подробнее в разделе @ref sect_gen_frame_wr).

Скорость может быть задана явно с помощью поля [IntfTransfRate](@ref TLTR210_CONFIG::IntfTransfRate). По-умолчанию установлена скорость 500 КСлов/с. При этом, если установленное значение превышает максимально допустимое значение скорости для крейта (в случае скорости 500 КСлов/c и LTR-U-1), то библиотека автоматически запишет корректное значение. Т.е. по-умолчанию используется максимально возможная для используемого крейта скорость.

Явное указание скорости может использоваться в случае большого количества модулей LTR210, для которых время выдачи кадра может пересекается во времени, чтобы не превысить максимальную пропускную способность интерфейса крейт  \f$\to\f$ компьютер.


<B>Пример</B>: Пусть используется LTR-EU-16 с 16-ю модулями LTR210, подключенный по интерфейсу Ethernet. Если все модули будут одновременно передавать записанный кадр со скоростью 500 КСлов/с, то суммарная скорость составит 8 МСлов/c (24 МБайт/c), что превышает максимальную скорость передачи крейта по Ethernet (порядка 10 МБайт/c или 2.5 МСлов/c). То есть, крейт не сможет передавать данные в ПК с той же скоростью, что принимает, и при определенных размерах кадров может произойти переполнение внутреннего буфера крейта. В этом случае можно для модулей установить скорость выдачи в интерфейс, равную 100 КСлов/c, что снизит скорость общего потока до 1.6 МСлов/c.


Таким образом, при большом количестве модулей следует всегда оценивать общую скорость передачи данных всех модулей крейта (а также нескольких крейтов, если они подключены к одной сети), учитывая и модули других типов (не LTR210), и, при необходимости, явно уменьшать скорость выдачи данных в интерфейс для избежания переполнения внутреннего буфера крейта.

Настройка режима дополнительного бита в потоке данных от АЦП{#sect_dig_bit_mode}
--------------------------------------------------------------------------------------
В модуле LTR210 в месте с отсчетами АЦП передается дополнительный бит данных. Что конкретно будет отображать этот бит, можно настроить независимо для каждого канала АЦП с помощью поля [DigBitMode](@ref TLTR210_CHANNEL_CONFIG::DigBitMode). Например, этот бит может отображать уровень на входе SYNC, что позволяет, при необходимости, использовать этот вход для синхронного ввода одного цифрового бита. Другие возможности приведены в описании типа #e_LTR210_DIG_BIT_MODE, задающего режим данного бита.

При обработке данных с помощью LTR210_ProcessData() значение данного бита сохраняется в массив структур с дополнительной информацией (если в качестве параметра data_info был передан ненулевой указатель). Каждая структура соответствует своему отчету из обработанных данных, что позволяет выполнить однозначное соответствие.

Принцип записи и выдачи кадра{#sect_gen_frame_wr}
===============================================================

В отличие от большинства других АЦП от "Л Кард", основной режим использования модуля LTR210 не предполагает непрерывного сбора данных. Вместо этого, при вызове LTR210_Start() модуль включает запись данных во внутренний кольцевой буфер в SRAM самого модуля размером на 16 МСлов (определено константой #LTR210_INTERNAL_BUFFER_SIZE) и ожидает наступление указанного события синхронизации.

Только при возникновении события синхронизации модуль выдает кадр данных в интерфейс модуль \f$\to\f$ крейт (далее просто интерфейс) в соответствии с параметрами кадра, описанными в разделе @ref sect_gen_cfg_frame.

Сразу после завершения передачи кадра по интерфейсу модуль готов к выдачи следующего кадра по событию синхронизации. Все события синхронизации, которые произошли от момента начала выдачи кадра в интерфейс (момента возникновения соответствующего синхрособытия) до момента завершения выдачи будут потеряны, при этом в [статусе кадра](@ref sect_gen_frame_status) будет указан флаг #LTR210_STATUS_FLAG_SYNC_SKIP.

Следует учесть, что скорость интерфейса между модулем и крейтом ограничена (200 КСлов/с для LTR-U-1 и 500 КСлов/c для остальных крейтов). Кроме того, ее можно, при необходимости, дополнительно ограничить с помощью специальной настройки (см. раздел @ref sect_gen_cfg_transf_rate). Таким образом, время выдачи кадра в интерфейс может существенно превышать время записи кадра во внутренний буфер модуля.

По-умолчанию модуль выполняет непрерывную запись во внутренний буфер. В таком режиме при определенных размерах кадра и частотах сбора АЦП может возникнуть ситуация, что процесс записи отсчетов в циклический буфер обгонит процесс чтения из буфера на круг и часть передаваемого кадра будет перетёрта новыми данными. Соответственно, в этом случае часть данных переданного кадра будет недействительна. Этот факт отражается в [статусе кадра](@ref sect_gen_frame_status) установкой флага #LTR210_STATUS_FLAG_OVERLAP.

Скорость записи данных в буфер равна \f$ N_{ch} * f_{acq} \f$, где \f$ f_{acq} \f$ --- частота сбора (см. раздел @ref sect_gen_cfg_adc_freq), а \f$ N_{ch} \f$ --- количество каналов, по которым разрешена запись. Если скорость записи ниже скорости чтения, то размер [FrameSize](@ref TLTR210_CONFIG::FrameSize) может быть любым, вплоть до \f$ \frac{LTR210\_FRAME\_SIZE\_MAX}{N_{ch}} \f$. Константа #LTR210_FRAME_SIZE_MAX задает максимальный размер кадра, который можно установить при одном разрешенном канале, что соответствует размеру внутреннего буфера за вычетом 512 слов --- размера блочной записи в SDRAM модуля.

В случае, если скорость записи больше скорости чтения, для гарантии, что не произойдет перетирание, время передачи кадра по интерфейсу должно быть меньше, чем время записи всего циклического буфера вместе с размером кадра за вычетом предыстории. Т.е. должно выполняться неравенство \f[ \frac{S + N_{ch}*(FrameSize - HistSize)}{f_{acq}*N_{ch}} \geq \frac{N_{ch}*FrameSize}{f_{intf}}\f] где S = #LTR210_FRAME_SIZE_MAX, \f$ f_{intf}\f$ -- скорость выдачи данных в интерфейс. 

Если задать в формуле размер предыстории как долю от размера всего кадра n: \f$ HistSize = n * FrameSize \f$, где n от 0 до 1, то можно можно переписать формулу в более удобный вид. Если необходимо узнать максимальный размер кадра при заданных частоте сбора АЦП, скорости выдачи данных в интерфейс и процентной доли предыстории, то формула выглядит следующим образом:

\f[ FrameSize \leq \frac{S*f_{intf}}{N_{ch} * (f_{acq}*N_{ch} - f_{intf}*(1-n))} \f]

Таблица с результатами данной формулы для некоторых типовых случаев приведена в документе [\"Крейтовая система LTR. Руководство пользователя\"](http://www.lcard.ru/download/ltr.pdf).

Для случая, если для заданных размеров кадра нужно определить максимальную частоту сбора, формула выглядит следующим образом:

\f[ f_{acq} \leq \frac{f_{intf}*(S/N_{ch} + FrameSize * (1-n))}{N_{ch} * FrameSize} \f]

Для того, чтобы иметь возможность установки полного размера буфера и при частотах сбора вплоть до максимальной, введен режим автоматической приостановки записи в кольцевой буфер. Этот режим устанавливается при конфигурации модуля с помощью установки флага #LTR210_CFG_FLAGS_WRITE_AUTO_SUSP в поле [Flags](@ref TLTR210_CONFIG::Flags) [структуры конфигурации](@ref TLTR210::Cfg). В этом режиме при возникновении события синхронизации выполняется запись во внутренний буфер до конца кадра, после чего процесс записи будет автоматически остановлен. При этом, запись будут возобновлена только после завершения выдачи всего кадра в интерфейс и перетирание данных невозможно. 

Плюсом режима автоматической приостановки записи является возможность записать кадр размером до \f$ \frac{LTR210\_FRAME\_SIZE\_MAX}{N_{ch}} \f$, независимо от частоты отсчетов АЦП. Минусом является то, что при ненулевом размере предыстории необходимо, чтобы после завершения выдачи кадра в интерфейс до возникновения следующего события синхронизации прошло время, необходимое для записи предыстории. В режиме же непрерывной записи при событии, произошедшем сразу после завершения передачи предыдущего кадра в интерфейс, кадр будет всегда записан успешно, независимо от размера предыстории.

Таким образом, при непрерывной записи интервал между соседними событиями синхронизации, чтобы ни одно событие не было пропущено, должен быть:
\f[ T_{sync\_cont} > \max (\frac{N_{ch} * FrameSize}{f_{intf}}, \frac{FrameSize-HistSize}{f_{acq}} ) \f]
а в режиме с автоматической приостановкой записи:
\f[ T_{sync\_susp} > T_{sync\_cont} + \frac{HistSize}{f_{acq}} \f]




Прием данных в режиме покадрового сбора{#sect_gen_frame_mode}
===================================================================================

Как было уже описано, в штатном режиме работы от модуля нет непрерывного потока данных, а данные передаются асинхронно по кадрам. Кроме того, помимо кадров данных модуль может периодически передавать свое слово состояния (подробнее описано в разделе @ref sect_gen_keepalive). В связи с этим операция приема данных несколько отличается от других модулей LTR. Вначале необходимо дождаться события прихода каких-либо данных от модуля. Для этого служит функция LTR210_WaitEvent(), которая ожидает в течение таймаута прихода слова данных от модуля, анализирует это слово и возвращает в параметре <I>event</I>, что за данные пришли.

Если это начало кадра (#LTR210_RECV_EVENT_SOF), то далее следует прочитать кадр данных аналогично тому, как это делается и для остальных модулей LTR: сперва почитать [RecvFrameSize](@ref TLTR210_STATE::RecvFrameSize) слов, принятых от модуля, с помощью LTR210_Recv(), а затем обработать их с помощью LTR210_ProcessData(). При желании кадр можно принимать и/или обрабатывать не целиком, а блоками меньшего размера, однако следует учитывать, что только после обработки последнего блока будет известен статус кадра и можно будет сделать вывод о действительности принятых данных.

Важно отметить, что первое слово кадра при передаче от модуля в крейт/ПК отмечается специальным образом и LTR210_WaitEvent() возвращает #LTR210_RECV_EVENT_SOF именно при нахождении начала кадра. Если LTR210_WaitEvent() будет вызвано в середине не до конца принятого кадра, то слова неполного кадра будут отброшены.

Также LTR210_Recv(), в отличие от аналогичных функций остальных модулей, при обнаружении конца кадра немедленно вернет данные до конца кадра, даже если запрашивалось больше данных и таймаут еще не истек.


Анализ статуса принятого кадра{#sect_gen_frame_status}
===========================================
Как уже отмечалось, в кадре помимо слов с отсчетами АЦП последним словом передается статус кадра, по которому и можно сделать вывод, верны ли данные в кадре. Информация о статусе кадра возвращается функцией LTR210_ProcessData() в виде структуры типа #TLTR210_FRAME_STATUS. 

По значению поля [Result](@ref TLTR210_FRAME_STATUS::Result) можно сделать общий вывод, был ли найден конец кадра и, если найден, действительны ли данные в принятом кадре. Если слово со статусом кадра не было найдено, то поле [Result](@ref TLTR210_FRAME_STATUS::Result) равно #LTR210_FRAME_RESULT_PENDING (например, в случае, если пользователь обрабатывает кадр по частям). Если же слово статуса кадра найдено, то [Result](@ref TLTR210_FRAME_STATUS::Result) = #LTR210_FRAME_RESULT_OK, если все данные действительны, либо #LTR210_FRAME_RESULT_ERROR, если часть из данных повреждена. 

Поле [Flags](@ref TLTR210_FRAME_STATUS::Flags) содержит полную информацию о статусе кадра в виде побитовой комбинации набора флагов и может служить для более детального анализа состояния кадра. В частности, по этим флагам можно узнать причину повреждения данных, если было возвращено значение [Result](@ref TLTR210_FRAME_STATUS::Result) = #LTR210_FRAME_RESULT_ERROR.

Следующие флаги относятся непосредственно к принятому кадру:
- #LTR210_STATUS_FLAG_OVERLAP --- признак, что процесс записи обогнал процесс чтения и часть данных в кадре была перетерта. Нельзя утверждать, какие данные в кадре являются действительными, а какие нет. Поле [Result](@ref TLTR210_FRAME_STATUS::Result) устанавливается в #LTR210_FRAME_RESULT_ERROR. Подробнее о причине возникновения данного события описано в разделе @ref sect_gen_cfg_frame.
- #LTR210_STATUS_FLAG_INVALID_HIST --- признак, что событие синхронизации произошло раньше, чем было записано [HistSize](@ref TLTR210_CONFIG::HistSize) точек для каждого канала и предыстория в принятом кадре не действительна. Поле [Result](@ref TLTR210_FRAME_STATUS::Result) устанавливается в #LTR210_FRAME_RESULT_ERROR, однако при отсутствии других флагов ошибки можно предположить, что часть кадра, относящаяся к времени после возникновения синхрособытия, верна. При непрерывной записи в буфер возникновение такой ситуации возможно только в случае, если событие синхронизации произошло непосредственно после начала записи с помощью LTR210_Start() и [HistSize](@ref TLTR210_CONFIG::HistSize) \f$\ne\f$ 0 и только в первом принятом кадре после разрешения записи. При включенной автоматической приостановке записи возникновение этого флага возможно в случае прихода следующего события синхронизации раньше, чем было записано [HistSize](@ref TLTR210_CONFIG::HistSize) точек для каждого канала с момента завершения выдачи в 
интерфейс предыдущего кадра.
- #LTR210_STATUS_FLAG_SYNC_SKIP --- признак, что во время записи и выдачи кадра в интерфейс произошло одно или несколько событий синхронизации, которые были отброшены, так как выдача предыдущего кадра не была закончена. Этот флаг не влияет на действительность данных и, соответственно, на значение поля [Result](@ref TLTR210_FRAME_STATUS::Result).

Кроме этого, в флагах передается информация:
  - По каким каналам разрешена запись.
  - Состояние захвата PLL модуля. При этом при отсутствии признака захвата PLL LTR210_ProcessData() вернет ошибку #LTR210_ERR_PLL_NOT_LOCKED, так как данный факт свидетельствует о неисправности модуля.

Все значения флагов приведены в описании типа #e_LTR210_STATUS_FLAGS.



Контроль работы модуля с помощью периодических статусов (сигнала жизни){#sect_gen_keepalive}
==============================================================================================
Так как в режиме покадрового сбора при отсутствие событий синхронизации модуль ведет запись лишь во внутренний кольцевой буфер и не передает никаких данных в крейт/ПК, то в такой ситуации нет информации, по которой можно судить о исправности модуля. Если необходима дополнительная проверка того, что модуль исправно выполняет запись во внутренний буфер и проверку условий синхронизации, то можно разрешить периодическую посылку модулем своего слова состояния. Для этого необходимо при настройке конфигурации модуля установить флаг #LTR210_CFG_FLAGS_KEEPALIVE_EN в поле [Flags](@ref TLTR210_CONFIG::Flags) [структуры конфигурации](@ref TLTR210::Cfg) до вызова LTR210_SetADC(). В этом случае, после разрешения записи вызовом LTR210_Start() модуль будет раз в 500 мс передавать свое слово состояние вплоть до запрета записи вызовом LTR210_Stop(). При этом слова состояния передаются только в момент, когда не идет передача кадра (т.е. они могут быть лишь между кадрами, но не внутри самого кадра), благодаря чему размер слов в 
кадре остается
неизменным и процедура его приема не отличается для случаев включенной или выключенной периодической передаче статуса модуля.

Периодическая передача статуса может быть использована в качестве сигнала жизни модуля --- отсутствие слов статуса от модуля в течение заданного интервала служит признаком неисправности модуля. Следует иметь ввиду, что этот интервал должен быть больше 500мс (например, несколько секунд), так как должен учитывать все возможные задержки как передачи данных по интерфейсу между крейтом и ПК, так и возможные программные задержки получения данных в сервере и программе верхнего уровня.

При обнаружении прихода статуса от модуля, LTR210_WaitEvent() вернет событие #LTR210_RECV_EVENT_KEEPALIVE. Кроме того, в параметре <I>status</I> (если не был передан нулевой указатель) будет сохранена дополнительная информация из пришедшего статуса. Она аналогична информации в [статусе кадра](@ref sect_gen_frame_status), за исключением отсутствия флагов, которые относятся непосредственно к принятому кадру. Таким образом, в периодическом статусе доступна следующая информация:
  - По каким каналам разрешена запись
  - Состояние захвата PLL модуля. При этом при отсутствии признака захвата PLL LTR210_WaitEvent() вернет ошибку #LTR210_ERR_PLL_NOT_LOCKED, так как данный факт свидетельствует о неисправности модуля
  
Проверку наличия сигнала жизни (статуса) в течение заданного интервала можно выполнять одним из следующих способов:
1. Можно в цикле приема вызывать LTR210_WaitEvent() с таймаутом, равным интервалу в течение которого считается, что статус должен обязательно прийти. Если по истечению таймаута не произошло никакого события (LTR210_WaitEvent() вернула событие #LTR210_RECV_EVENT_TIMEOUT), то это свидетельствует о неисправности модуля.
2. Можно вызывать LTR210_WaitEvent() с меньшим таймаутом, и в случае, если никакого события не произошло, проверить, сколько времени прошло с момента прихода последних данных от модуля, вызвав LTR210_GetLastWordInterval(). Если этот интервал превышает порог, то можно считать, что модуль неисправен. Этот способ позволяет, в частности, интерактивно остановить сбор данных, так как не требует ожидания в LTR210_WaitEvent() больших таймаутов.


Режим непрерывного сбора данных{#sect_gen_stream_mode}
========================================================
Для настройки непрерывного сбора данных нужно установить [SyncMode](@ref TLTR210_CONFIG::SyncMode) = #LTR210_SYNC_MODE_CONTINUOUS. В этом режиме параметры кадра ([FrameSize](@ref TLTR210_CONFIG::FrameSize) и [HistSize](@ref TLTR210_CONFIG::HistSize)) не имеют значение, а [GroupMode](@ref TLTR210_CONFIG::GroupMode) должен быть равен #LTR210_GROUP_MODE_INDIVIDUAL (значение по-умолчанию). 

Кроме того, в режиме непрерывного сбора есть ограничение на частоту сбора АЦП. Это ограничение связано с ограничением скорости передачи данных по интерфейсу между модулем и крейтом. Для LTR-U-1 должно выполняться неравенство \f$ N_{ch}*f_{acq} \leq 200\f$ КГц, а для остальных крейтов \f$ N_{ch}*f_{acq} \leq 500\f$ КГц. Данные условия проверяются при вызове LTR210_SetADC().

Также для непрерывного сбора данных не используется посылка статусов жизни, т.е. флаг #LTR210_CFG_FLAGS_KEEPALIVE_EN не имеет значение.

В режиме непрерывного сбора по вызову LTR210_Start() начинается сбор данных с АЦП и выдача их в интерфейс. Прием данных осуществляется аналогично остальным модулям LTR с АЦП с помощью LTR210_Recv() и LTR210_ProcessData(). Модуль не передает никаких статусных слов, так как поток отсчетов не разбит на кадры. Таким образом, в качестве результата обработки кадра LTR210_ProcessData() всегда возвращает #LTR210_FRAME_RESULT_PENDING и эти данные не несут какой-либо дополнительной информации, поэтому как правило в качестве <I>frame_status</I> можно передавать нулевой указатель.


Особенности калибровки данных модулем{#sect_gen_cbr}
===========================================================
Следует отметить, что в отличие от большинства остальных модулей LTR, калибровка данных происходит аппаратно внутри модуля, а не программно. В связи с этим в LTR210_ProcessData() нет никаких указаний о выполнении калибровки. Самой библиотекой выполняется чтение калибровочных коэффициентов из Flash-памяти модуля, сохранение их в полях массива [CbrCoef](@ref TINFO_LTR210::CbrCoef) в [структуре с информацией о модуле](@ref TINFO_LTR210) и запись этих коэффициентов в ПЛИС.

ПЛИС налету выполняет калибровку по формуле \f$ Y = (X + Offset)*Gain \f$, где X --- отсчет с АЦП, Y --- калиброванные данные, Offset --- смещение шкалы, а Gain --- коэффициент шкалы. При этом перед выполнением калибровки, входное значение АЦП расширяется на 1 бит. Уже откалиброванные 15-битные отсчеты передаются в крейт. При этом код #LTR210_ADC_SCALE_CODE_MAX соответствует напряжению, равному максимальному напряжению для заданного диапазона.

Коррекция АЧХ {#sect_afc_cor}
===========================================================
В библиотеке реализована возможность выполнения коррекции амплитудно-частотной характеристики (АЧХ) модуля.

Для всех диапазонов может выполняться корректировка наклона АЧХ с помощью КИХ-фильтра второго порядка в соответствии с методом, описанным в статье [Метод тонкой коррекции наклона АЧХ с помощью простого цифрового фильтра](http://www.lcard.ru/download/simple_fir_filter.pdf). Во Flash-памяти модуля сохранено значение отношения измеренной амплитуды сигнала заданной частоты, выполненное при максимальной частоте сбора АЦП (10 МГц), к амплитуде сигнала с наименьшей частотой для каждого канала и диапазона, а также значение частоты сигнала в Гц. 

Кроме того, для диапазонов \f$\pm10\f$ В и \f$\pm5\f$ В может выполняться дополнительная коррекция излома АЧХ в низкочастотной области с помощью БИХ-фильтра в соответствии с методом, описанным в статье [Простой БИХ-фильтр коррекции излома АЧХ в низкочастотной области полосы частот пропускания](http://www.lcard.ru/download/simple_iir_filter.pdf). Во Flash-памяти храняться параметры <B>R2</B> и <B>C</B> (<B>R1</B> всегда равен 1) эквивалентной схемы фильтра для корректировки АЧХ на максимальной частоте дискретизации (10 МГц). БИХ-фильтр применяется до КИХ-фильтра (при этом в записанном во Flash-память коэффициенте КИХ-фильтра учитывается вносимые БИХ-фильтром изменения АЧХ).

Все параметры для коррекции АЧХ считываются из  Flash-памяти модуля при его открытии вместе с калибровочными коэффициентами и сохраняется в соответствующие поля [структуры с информацией о модуле](@ref TINFO_LTR210).


При настройке модуля с помощью LTR210_SetADC() библиотека, используя упомянутые выше параметры, выполняет расчет коэффициентов фильтра для заданной частоты дискретизации, если они уже не были рассчитаны при предыдущем запуске. При обработке принятых данных в функцию LTR210_ProcessData() можно передать флаг #LTR210_PROC_FLAG_AFC_COR, который указывает, что для полученных данных необходимо применить рассчитанный фильтр/фильтры для корректировки АЧХ модуля.


Измерение и коррекция смещения нуля {#sect_zero_cor}
===========================================================
В LTR210 есть возможность выполнять измерение собственного нуля. Это позволяет при необходимости учесть смещение нуля, которое может быть связано либо с его временным уходом, либо с изменением окружающих условий. Для этого необходимо выполнить измерение собственного нуля непосредственно перед началом записи и при дальнейшем сборе, вычтя из полученных отсчетов измеренное значение нуля, получить скорректированные измерения. Смещение нуля зависит от использованных диапазонов и канала, поэтому измерение нуля нужно выполнять для тех же настроек, что и дальнейшие измерения.

Хотя пользователь может запрограммировать этот алгоритм при необходимости и сам, библиотека предоставляет функции для облегчения данной операции. Функция LTR210_MeasAdcZeroOffset() выполняет измерение собственного нуля для заданных в конфигурации модуля диапазонов. Ее необходимо вызывать после настройки АЦП перед разрешением записи данных. Рассчитанные значения сохраняются в поле [AdcZeroOffset](@ref TLTR210_STATE::AdcZeroOffset) структуры [состояния модуля](@ref TLTR210_STATE). 

В дальнейшем, при обработке данных, в LTR210_ProcessData() можно передать флаг #LTR210_PROC_FLAG_ZERO_OFFS_COR, в результате чего LTR210_ProcessData() вычтет сохраненные измеренные значения смещения нуля из обрабатываемых отсчетов.

Следует при этом отметить, что с момента измерения смещения нуля с помощью  LTR210_MeasAdcZeroOffset() до обработки данных диапазоны каналов не должны меняться. При смене диапазонов требуется повторное измерение смещения нуля.

Вызов функций библиотеки из разных потоков{#sect_get_multithread}
=====================================================================
Функции библиотеки ltr210api, как и библиотек для работы с другими модулями LTR, не являются потокобезопасными. То есть пользователь сам должен гарантировать, что вызовы функций для работы с одним и тем же модулем выполняются последовательно (естественно, возможна параллельная работа с разными модулями из разных потоков). 

Однако, для удобства использования из этого правила есть исключения. На фоне приема данных в отдельном потоке с помощью LTR210_WaitEvent(), LTR210_Recv() и LTR210_ProcessData() можно вызывать из другого потока следующие функции:
- LTR210_FrameStart() для вызова программного события синхронизации
- LTR210_SetADC() для обновления на лету части настроек

Это позволяет вызывать LTR210_FrameStart() и LTR210_SetADC() из потока пользовательского интерфейса даже в случае, если сам сбор выполняется в отдельном потоке.
