Doxygen — различия между версиями
Korogodin (обсуждение | вклад) (→Graphiz) |
Korogodin (обсуждение | вклад) |
||
(не показаны 13 промежуточных версий 1 участника) | |||
Строка 7: | Строка 7: | ||
Для html-представления документации, размещаемого на web-серверах, существует удобный способ организации поиска (при помощи создаваемого Doxygen'ом PHP-модуля) и ссылок на внешнюю документацию. | Для html-представления документации, размещаемого на web-серверах, существует удобный способ организации поиска (при помощи создаваемого Doxygen'ом PHP-модуля) и ссылок на внешнюю документацию. | ||
− | Doxygen - консольная программа в духе классической Unix. Она работает подобно компилятору, анализируя исходные тексты и создавая документацию. | + | Doxygen - консольная программа в духе классической Unix. Она работает подобно компилятору, анализируя исходные тексты и создавая документацию. |
+ | |||
== Что требуется установить для полноценной работы == | == Что требуется установить для полноценной работы == | ||
+ | |||
=== Doxygen === | === Doxygen === | ||
Основная программа | Основная программа | ||
+ | |||
=== Graphiz === | === Graphiz === | ||
[http://ru.wikipedia.org/wiki/Graphviz Graphviz] – это свободно распространяемый пакет утилит для визуализации данных. Нам он нужен для того, чтобы Doxygen мог показать в документации отношения наследования, графы вызовов и прочую информацию в виде наглядных изображений. | [http://ru.wikipedia.org/wiki/Graphviz Graphviz] – это свободно распространяемый пакет утилит для визуализации данных. Нам он нужен для того, чтобы Doxygen мог показать в документации отношения наследования, графы вызовов и прочую информацию в виде наглядных изображений. | ||
+ | |||
=== LaTeX === | === LaTeX === | ||
При установленном пакете того или иного LaTeX-дистрибутива, Doxygen конвертирует TeX-разметку в комментариях в изображения, а затем вставляет их в итоговый отчет. Также генерирует TeX-файлы, а затем PDF. | При установленном пакете того или иного LaTeX-дистрибутива, Doxygen конвертирует TeX-разметку в комментариях в изображения, а затем вставляет их в итоговый отчет. Также генерирует TeX-файлы, а затем PDF. | ||
+ | |||
=== Doxywizard === | === Doxywizard === | ||
Строка 1309: | Строка 1314: | ||
</div> | </div> | ||
− | == | + | |
+ | ==Комментирование исходного текста== | ||
+ | Практически любой элемент программы (класс, функция, переменная) может быть задокументирован в системе Doxygen.<br> | ||
+ | Документирование выполняется на основе двух видов комментариев:<br> | ||
+ | * краткий (brief) | ||
+ | * и полный (detailed). | ||
+ | |||
+ | Краткие комментарии обычно описывают предназначение комментируемого элемента, а полные содержат информацию по его использованию и функционированию и чаще всего являются многострочными.<br> | ||
+ | К каждому элементу программы не может быть привязано более одного краткого и полного комментария.<br> | ||
+ | Для документирования какого-либо элемента программы, соответствующий комментарий располагают перед этим элементом в тексте программы. Например: | ||
+ | |||
+ | //! Оценка вектора состояния СС за дисперсией квадратурных компонент | ||
+ | int x_stdn2_est; | ||
+ | |||
+ | Существует множество вариантов оформления комментариев:<br> | ||
+ | |||
+ | * Возможно использовать комментарии в стиле системы JavaDoc, применяемой при документировании исходных текстов на языке Java: | ||
+ | |||
+ | /** | ||
+ | * Оценка вектора состояния СС за дисперсией квадратурных компонент | ||
+ | */ | ||
+ | int x_stdn2_est; | ||
+ | |||
+ | или так | ||
+ | |||
+ | /*! | ||
+ | * Оценка вектора состояния СС за дисперсией квадратурных компонент | ||
+ | */ | ||
+ | int x_stdn2_est; | ||
+ | |||
+ | как и для предыдущего случая, знаки "*" не обязательны для промежуточных строк: | ||
+ | |||
+ | /*! | ||
+ | Оценка вектора состояния СС за дисперсией квадратурных компонент | ||
+ | */ | ||
+ | int x_stdn2_est; | ||
+ | |||
+ | * Еще один вариант - использование дополнительных знаков "/" или "!" в каждой строке (QT-Style): | ||
+ | |||
+ | /// | ||
+ | /// Оценка вектора состояния СС за дисперсией квадратурных компонент | ||
+ | /// | ||
+ | int x_stdn2_est; | ||
+ | |||
+ | или | ||
+ | |||
+ | //! | ||
+ | //! Оценка вектора состояния СС за дисперсией квадратурных компонент | ||
+ | //! | ||
+ | int x_stdn2_est; | ||
+ | |||
+ | |||
+ | По умолчанию любой многострочный комментарий является подробным. Для объявления кратких комментариев можно так же использовать несколько методов:<br> | ||
+ | |||
+ | * Использование команды \brief в блоке комментария: | ||
+ | |||
+ | /*! \brief краткий комментарий. | ||
+ | * краткий комментарий. | ||
+ | * | ||
+ | * после пустой строки начинается подробный комментарий. | ||
+ | */ | ||
+ | int x_stdn2_est; | ||
+ | |||
+ | 2.Для однострочных комментариев: | ||
+ | |||
+ | /// краткое описание. | ||
+ | /** Полное описание. */ | ||
+ | int x_stdn2_est; | ||
+ | |||
+ | или | ||
+ | |||
+ | //! краткое описание. | ||
+ | //! многострочное | ||
+ | //! подробное описание. | ||
+ | int x_stdn2_est; | ||
+ | |||
+ | Иногда желательно расположить комментарий после, либо на одной строке с описываемым элементом. Для такого случая так же существуют несколько возможных способов:<br> | ||
+ | |||
+ | 1. int x_stdn2_est;; /*!< Подробный комментарий */ | ||
+ | 2. int x_stdn2_est;; /**< Подробный комментарий */ | ||
+ | 3. int x_stdn2_est;; //!< Подробный комментарий | ||
+ | 4. //!< | ||
+ | 5. int x_stdn2_est;; ///< Подробный комментарий | ||
+ | ///< | ||
+ | 6. int x_stdn2_est;; //!< Краткий комментарий | ||
+ | 7. int x_stdn2_est;; ///< Краткий комментарий | ||
+ | |||
+ | |||
+ | Обычно предполагается, что документирующие комментарии находятся рядом с документируемым элементом. Однако, Doxygen позволяет поместить комментарий практически в любой части файла, связав его с каким-либо элементом. В этом случае необходимо указывать в блоке комментария ряд специальных команд.<br> | ||
+ | Например так будет выглядеть описание класса Test, размещенное в любом месте файла:<br> | ||
+ | |||
+ | /*! \class Test | ||
+ | \brief Тестовый класс. | ||
+ | |||
+ | Полное описание класса. | ||
+ | */ | ||
+ | |||
+ | Кроме команды \class, можно использовать множество других:<br> | ||
+ | \struct - документирует структуру | ||
+ | \union - документирует объединение | ||
+ | \enum - документирует перечисление | ||
+ | \fn - документирует функцию | ||
+ | \var - документирует переменную | ||
+ | \def - документирует макрос подстановки #define | ||
+ | \file - документирует файл | ||
+ | \namespace - документирует пространство имен. | ||
+ | \typedef - документирование объявления типа | ||
+ | \interface - документирование IDL интерфейса | ||
+ | \package - документирование пакета на языке Java | ||
+ | |||
+ | |||
+ | == Востребованные команды == | ||
+ | |||
+ | |||
+ | === Комментирование структур, переменных и т.д. === | ||
+ | |||
+ | Переменные часто удобно объединять в группы: | ||
+ | <source lang="c"> | ||
+ | /** @name Аккумуляторы и их триггеры */ | ||
+ | quint32 R2; ///< Первичный акк. \f$ I^2 + Q^2 \f$ | ||
+ | quint64 R4; ///< Первичный акк. \f$ (I^2 + Q^2)^2 \f$ | ||
+ | |||
+ | quint32 R2_acum; ///< Вторичный аккумулятор R2 | ||
+ | quint64 R4_acum; ///< Вторичный аккумулятор R4 | ||
+ | |||
+ | quint32 R2_acum_copy; ///< Триггер R2_acum | ||
+ | quint64 R4_acum_copy; ///< Триггер R4_acum | ||
+ | //@} | ||
+ | </source> | ||
+ | |||
+ | |||
+ | === Комментирование функции === | ||
+ | |||
+ | <source lang="c"> | ||
+ | /** | ||
+ | Позволяет установить оценку дисперсии (мощности шумовой составляющей) корреляционных сумм и | ||
+ | зафиксировать её. | ||
+ | @param PoMe - указатель на структуру данных блока оценки с/ш | ||
+ | @param stdn2_IQ - устанавливаемое значение оценки дисперсии квадратур | ||
+ | @return 0, если прошло успешно, 1, если предлагаемое число после сдвига не влазиет в 32 разряда | ||
+ | */ | ||
+ | int SetVariancePowerMeasure(PowerMeasure_struct *PoMe, quint32 stdn2_IQ ){ | ||
+ | if (__CLZ(stdn2_IQ) >= x_stdn2_shift){ // Если предлагаемое число можно сдвинуть, не переполнив 32 разряда | ||
+ | PoMe->x_stdn2_est = stdn2_IQ; | ||
+ | // В случае увеличения порядка фильтра добавить сюда PoMe->x_stdn2_extr = stdn2_IQ; | ||
+ | PoMe->x_stdn2_est_shifted = stdn2_IQ<<x_stdn2_shift; | ||
+ | return 0; | ||
+ | }else return 1; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | |||
+ | === Вставка TeX-формул === | ||
+ | |||
+ | Для вставки TeX-формулы используются команды <code>\f$ ... \f$</code> и <code>\f[ ... \f] </code>, которые обрамляют TeX-разметку: | ||
+ | |||
+ | Выражение в тексте: | ||
+ | <source lang="c"> | ||
+ | /** Всё гениальное просто: \f$ E = mc^2 \f$ */ | ||
+ | </source> | ||
+ | |||
+ | |||
+ | Выражение по центру, с новой строки: | ||
+ | <source lang="c"> | ||
+ | /** Воспользуемся дискриминатором | ||
+ | \f[ | ||
+ | u_{d,k} = - atan{frac{Q_k}{I_k}}, | ||
+ | \f] | ||
+ | его характеристики хорошо изучены, работа наглядна. | ||
+ | */ | ||
+ | </source> | ||
+ | |||
+ | |||
+ | Для расширенного синтаксиса нужно дополнить опцию в Doxyfile'e: | ||
+ | <source lang="bash"> | ||
+ | EXTRA_PACKAGES = amssymb,amsfonts,amsmath,mathtext | ||
+ | </source> | ||
+ | |||
+ | |||
+ | === Bug, ToDo, Warning, Note === | ||
+ | |||
+ | Одноименные команды вставляют одноименные заметки. Далее doxygen формирует отдельные списки, по которым можно быстро найти интересующее место в коде. | ||
+ | |||
+ | <source lang="c"> | ||
+ | /** | ||
+ | @warning Не трогать значение этой переменной | ||
+ | @todo Переписать функцию под новую структуру данных | ||
+ | @bug Ошибочно работает при x<0 | ||
+ | @note Подробнее изложено в рабочем журнале | ||
+ | */ | ||
+ | </source> | ||
+ | |||
+ | == Пример из жизни == | ||
+ | |||
+ | Пример документирования файлов PowerMeasure.c и PowerMeasure.h. Результат можно подглядеть [http://server.srns.ru/doxygen/examples/PowerMeasure_DoxyDoc/index.html тут]. | ||
+ | |||
+ | <div class="NavFrame collapsed"> | ||
+ | <div class="NavHead">PowerMeasure.c</div> | ||
+ | <div class="NavContent"> | ||
+ | <source lang="c"> | ||
+ | #include "PowerMeasure.h" | ||
+ | |||
+ | #if (RECEIVER_TYPE == RECEIVER_ALPACA) | ||
+ | #include <math.h> | ||
+ | #include "FPGA.h" | ||
+ | #else if (RECEIVER_TYPE == RECEIVER_NIIKP_ARM) | ||
+ | #include "std.h" | ||
+ | #include <intrinsics.h> | ||
+ | #endif | ||
+ | |||
+ | quint32 sqrt_PoMe(quint32 x); | ||
+ | quint32 NearestPower2(quint32 x); // Ближайщее большее 2^n, возвращаем n | ||
+ | |||
+ | |||
+ | /** | ||
+ | Инициализация структуры данных блока оценки с/ш, сброс счетчиков. | ||
+ | @param PoMe - указатель на структуру данных блока оценки с/ш | ||
+ | @param Init_qcno - инициализационное значение отношения с/ш, в НИИ КП не используется | ||
+ | */ | ||
+ | void InitPowerMeasure(PowerMeasure_struct * PoMe, quint32 Init_qcno) | ||
+ | { | ||
+ | PoMe->x_A2_est[0] = (1<<PoMe_NoiseU2Bit_shifted<<5); | ||
+ | |||
+ | PoMe->x_stdn2_est = (1<<PoMe_NoiseU2Bit_shifted); // Для первого порядка совпадает с экстраполяцией | ||
+ | PoMe->x_stdn2_est_shifted = PoMe->x_stdn2_est << x_stdn2_shift; | ||
+ | PoMe->allow_stnd2_est = 1; // Разрешить оценивать и фильтровать дисперсию квадратур | ||
+ | |||
+ | PoMe->R2 = 0; | ||
+ | PoMe->R4 = 0; | ||
+ | |||
+ | PoMe->acum_counter = 0; // Счетчик второго уровня накопителя корреляционных сумм | ||
+ | PoMe->sum_counter = 0; // Счетчик первого уровня накопителя корреляционных сумм | ||
+ | |||
+ | PoMe->fail_counter = 0; // Счетчик подряд идущих фейлов измерений | ||
+ | |||
+ | PoMe->start_counter = 0; // Счетчик тиков фильтра СКО от разрешения, доходит до (obr_Kf_stdn_0+задержка) и застывает | ||
+ | |||
+ | PoMe->acum_threshold_lock = 0; | ||
+ | |||
+ | #if (RECEIVER_TYPE == RECEIVER_ALPACA) | ||
+ | if (Init_qcno > 0) | ||
+ | PoMe->qcno = Init_qcno; | ||
+ | else | ||
+ | PoMe->qcno = (quint32)( PoMe->x_A2_est[0] / (2.0 * PoMe->x_stdn2_est * PoMe_Tcorr) ); | ||
+ | PoMe->qcno_dBHz = 10.0*log10(PoMe->qcno); | ||
+ | PoMe->qcno_dBHz_extr = PoMe->qcno_dBHz; | ||
+ | #endif | ||
+ | } | ||
+ | |||
+ | |||
+ | /** | ||
+ | По накопленным \f$\sum I_k^2+Q_k^2\f$ и \f$\sum (I_k^2+Q_k^2)^2\f$ производим | ||
+ | оценки дисперсии, амплитуды и квадрата амплитуды квадратур. | ||
+ | Основная нить вычислений: | ||
+ | \f[ M = \frac{R2}{K} \f] | ||
+ | \f[ Diskrimi = 2M^2 - \frac{R4}{K} \f] | ||
+ | \f[ A^2_{izm} = M - 2 \sigma^2_{filt} \f] | ||
+ | \f[ \sigma^2_{izm} = \frac{M - \sqrt{Diskrimi}}{2} \f] | ||
+ | Измерения \f$ \sigma^2_{izm} \f$ хорошенько фильтруем, чтобы не испортить \f$ A^2_{izm} \f$ | ||
+ | @param PoMe - указатель на структуру данных блока оценки с/ш | ||
+ | */ | ||
+ | void DoPowerMeasure(PowerMeasure_struct *PoMe) | ||
+ | { | ||
+ | quint32 M; | ||
+ | quint32 Diskrimi; | ||
+ | quint32 SQ_stdn_izm; | ||
+ | quint32 SQ_A_izm; | ||
+ | //qint32 Ud_A; | ||
+ | qint32 Ud_stdn; | ||
+ | qint64 tmp64_1, tmp64_2, tmp64_3; | ||
+ | quint32 tmpu32_2, Diskrimi_shift; | ||
+ | |||
+ | /* Division by acum_counter */ | ||
+ | int clz=31-__CLZ(PoMe->Accumulators_are_ready); | ||
+ | if((1<<clz)==PoMe->Accumulators_are_ready) | ||
+ | { | ||
+ | tmp64_1 = PoMe->R2_acum_copy >> clz; // M | ||
+ | tmp64_3 = PoMe->R4_acum_copy >> clz; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | tmp64_1 = PoMe->R2_acum_copy / PoMe->Accumulators_are_ready; // M | ||
+ | tmp64_3 = PoMe->R4_acum_copy / PoMe->Accumulators_are_ready; | ||
+ | } | ||
+ | /***/ | ||
+ | |||
+ | PoMe->acum_threshold_lock = 0; | ||
+ | |||
+ | tmp64_2 = 2*tmp64_1*tmp64_1; | ||
+ | tmp64_2 = tmp64_2 - tmp64_3; // Diskrimi | ||
+ | if (tmp64_2 < 0)tmp64_2 = 0; | ||
+ | |||
+ | tmpu32_2 = ((tmp64_2 >> 32)&0xFFFFFFFF); | ||
+ | Diskrimi_shift = 32 - __CLZ(tmpu32_2); | ||
+ | if (Diskrimi_shift & 0x1) Diskrimi_shift++; // Чётное must be | ||
+ | M = (tmp64_1&0xFFFFFFFF); | ||
+ | Diskrimi = ((tmp64_2 >> Diskrimi_shift)&0xFFFFFFFF); | ||
+ | PoMe->Accumulators_are_ready = 0; | ||
+ | PoMe->IQ_Power = M; | ||
+ | |||
+ | /* Измерение квадрата амплитуды */ | ||
+ | if (M > 2*PoMe->x_stdn2_est){ | ||
+ | SQ_A_izm = M - 2*PoMe->x_stdn2_est; | ||
+ | PoMe->fail_counter = 0; | ||
+ | } | ||
+ | else { | ||
+ | PoMe->fail_counter++; | ||
+ | if (PoMe->x_A2_est[0] > (1<<PoMe_NoiseU2Bit_shifted) ) SQ_A_izm = (1<<PoMe_NoiseU2Bit_shifted); | ||
+ | else SQ_A_izm = PoMe->x_A2_est[0] - PoMe->x_A2_est[0]/2; //0.05*(0 - PoMe->x_A2_est[0]); | ||
+ | } | ||
+ | /***/ | ||
+ | |||
+ | |||
+ | /* Фильтр амплитуды и её квадрата */ | ||
+ | PoMe->x_A2_est[0] = SQ_A_izm; | ||
+ | PoMe->x_A_est = sqrt_PoMe( PoMe->x_A2_est[0] ); | ||
+ | /***/ | ||
+ | |||
+ | |||
+ | //#ifdef __Model | ||
+ | // static FILE* fid_ampout=0; | ||
+ | // if (!fid_ampout) | ||
+ | // { | ||
+ | // fid_ampout = fopen("amp.csv", "wt"); | ||
+ | // fprintf(fid_ampout,"tmp64_1;tmp64_2;tmp64_3;SQ_stdn;tmp;Diskrimi;M;SQ_A_izm\n"); | ||
+ | // } | ||
+ | // fprintf(fid_ampout,"%I64u;%I64u;%I64u;%d;%d;%u;%u;%u\n", | ||
+ | // tmp64_1,tmp64_2,tmp64_3, | ||
+ | // SQ_stdn_izm, | ||
+ | // tmp, | ||
+ | // Diskrimi, | ||
+ | // M, | ||
+ | // SQ_A_izm); | ||
+ | // fflush(fid_ampout); | ||
+ | //#endif | ||
+ | |||
+ | if (PoMe->allow_stnd2_est == 1){ | ||
+ | quint32 tmp; | ||
+ | /* Измерение квадрата СКО квадратур */ | ||
+ | if ( Diskrimi > 0 ) { | ||
+ | tmp = sqrt_PoMe(Diskrimi); | ||
+ | if (tmp != 0){ // Одна итерация по Герону для увеличения точности до требуемой | ||
+ | tmp += (int(Diskrimi) -int(tmp*tmp))/2 / int(tmp); // Обратное смещение с учетом смещения в корне | ||
+ | } | ||
+ | tmp <<= (Diskrimi_shift/2); | ||
+ | if (M > tmp) | ||
+ | SQ_stdn_izm = (M - tmp) / 2 ; // | ||
+ | else | ||
+ | SQ_stdn_izm = 0; | ||
+ | } else | ||
+ | SQ_stdn_izm = M / 2; | ||
+ | /***/ | ||
+ | |||
+ | if (SQ_stdn_izm > 2*PoMe->x_stdn2_est) // При резком изменении амплитуды на интервале оценивания | ||
+ | SQ_stdn_izm = 2*PoMe->x_stdn2_est; // происходит аномальный выброс, т.к. процесс не соответствует модели постоянства параметра | ||
+ | |||
+ | |||
+ | /* Фильтр диспресии квадратурных компонент */ | ||
+ | Ud_stdn = (SQ_stdn_izm<<x_stdn2_shift) - PoMe->x_stdn2_est_shifted; // Дискриминатор дисперсии квадратур | ||
+ | quint32 start_delay = 10; // First PoMe_obr_Kf_stdn_0 steps Kalman is used | ||
+ | if (PoMe->start_counter >= (PoMe_obr_Kf_stdn_0 + start_delay)) // После подстройки опять затягиваем фильтр | ||
+ | PoMe->x_stdn2_est_shifted += Ud_stdn / PoMe_obr_Kf_stdn_0; | ||
+ | else if (PoMe->start_counter < start_delay) { // На начальном этапе фильтр затянут | ||
+ | PoMe->start_counter++; | ||
+ | PoMe->x_stdn2_est_shifted += Ud_stdn / PoMe_obr_Kf_stdn_0; | ||
+ | } | ||
+ | else { // После выжидания start_delay расширяем фильтр и быстро подстраиваемся | ||
+ | PoMe->start_counter++; | ||
+ | PoMe->x_stdn2_est_shifted += Ud_stdn >> NearestPower2(PoMe->start_counter - start_delay); | ||
+ | } | ||
+ | PoMe->x_stdn2_est = PoMe->x_stdn2_est_shifted>>x_stdn2_shift; | ||
+ | /***/ | ||
+ | |||
+ | } // if (PoMe->allow_stnd2_est == 1) | ||
+ | |||
+ | |||
+ | #if (RECEIVER_TYPE == RECEIVER_ALPACA) | ||
+ | PoMe->SQ_A_izm = SQ_A_izm; | ||
+ | PoMe->SQ_stdn_izm = SQ_stdn_izm; | ||
+ | PoMe->qcno = (quint32)( PoMe->x_A2_est[0] / (2.0 * PoMe->x_stdn2_est * PoMe_Tcorr) ); | ||
+ | PoMe->qcno_dBHz = 10.0*log10(PoMe->qcno); | ||
+ | PoMe->qcno_dBHz_extr = PoMe->qcno_dBHz; | ||
+ | #endif | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | Сопоставляет выбранному номеру порога число требуемых накоплений второго уровня. | ||
+ | @param PoMe - указатель на структуру данных блока оценки с/ш | ||
+ | |||
+ | @todo Что-то слишком громозко и сложно, нужно переделать систему порогов | ||
+ | */ | ||
+ | void SetAccumThreshold(PowerMeasure_struct *PoMe){ | ||
+ | |||
+ | switch (PoMe->acum_threshold_level){ | ||
+ | case 5: | ||
+ | PoMe->acum_threshold = PoMe_Threshold_5; | ||
+ | break; | ||
+ | case 4: | ||
+ | PoMe->acum_threshold = PoMe_Threshold_4; | ||
+ | break; | ||
+ | case 3: | ||
+ | PoMe->acum_threshold = PoMe_Threshold_3; | ||
+ | break; | ||
+ | case 2: | ||
+ | PoMe->acum_threshold = PoMe_Threshold_2; | ||
+ | break; | ||
+ | case 1: | ||
+ | PoMe->acum_threshold = PoMe_Threshold_1; | ||
+ | break; | ||
+ | default: | ||
+ | PoMe->acum_threshold = PoMe_Threshold_def; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | Производит необходимые накопления суммы квадратов корреляционных сумм, | ||
+ | устанавливает пороги накопления по детектируемой мощности на входе, | ||
+ | при достижении порога вызывает функцию обработки накоплений DoPowerMeasure. | ||
+ | Различаются накопления двух уровней. | ||
+ | - первый: накопление PoMe_sum_counter_max величин U2, результат - детектор мощности | ||
+ | - второй: накопление acum_threshold сумм первого уровня, затем вызов DoPowerMeasure | ||
+ | @param PoMe - указатель на структуру данных блока оценки с/ш | ||
+ | @param U2 - сумма квадратов корреляционных сумм \f$U2 = I_k^2 + Q_k^2\f$ | ||
+ | */ | ||
+ | void AccumPowerMeasure(PowerMeasure_struct *PoMe, quint32 U2){ | ||
+ | |||
+ | quint64 tmpu64; | ||
+ | quint32 tmpu32; | ||
+ | int overflow_F_ = 0; | ||
+ | PoMe->sum_counter++; if (PoMe->sum_counter == PoMe_sum_counter_max) PoMe->sum_counter = 0; | ||
+ | |||
+ | tmpu32 = PoMe->R2 + U2; | ||
+ | if (PoMe->R2 <= tmpu32) // overflow defence | ||
+ | PoMe->R2 = tmpu32; // sum I^2 + Q^2 | ||
+ | else{ // impossible, if PoMe_sum_counter_max and U2_SHIFT are correct | ||
+ | PoMe->R2 = U2; | ||
+ | overflow_F_ = 1; | ||
+ | } | ||
+ | |||
+ | tmpu64 = PoMe->R4 + (quint64)(U2) * (quint64)(U2); | ||
+ | if ( (PoMe->R4 <= tmpu64) & (overflow_F_ == 0) ) // overflow defence | ||
+ | PoMe->R4 = tmpu64; // sum (I^2 + Q^2)^2 | ||
+ | else{ // impossible, if PoMe_sum_counter_max and U2_SHIFT are correct | ||
+ | PoMe->R4 = (quint64)(U2) * (quint64)(U2); | ||
+ | } | ||
+ | |||
+ | if (PoMe->sum_counter == (PoMe_sum_counter_max - 1) ) | ||
+ | { | ||
+ | quint64 tmpu64_1, tmpu64_2; | ||
+ | quint32 tmpu32_1, tmpu32_2; | ||
+ | if (overflow_F_ == 0){ | ||
+ | tmpu64_1 = PoMe->R4 / PoMe_sum_counter_max; | ||
+ | tmpu32_1 = PoMe->R2 / PoMe_sum_counter_max; | ||
+ | } else { | ||
+ | tmpu64_1 = PoMe->R4; | ||
+ | tmpu32_1 = PoMe->R2; | ||
+ | } | ||
+ | PoMe->R2 = 0; | ||
+ | PoMe->R4 = 0; | ||
+ | |||
+ | tmpu64_2 = PoMe->R4_acum + tmpu64_1; | ||
+ | tmpu32_2 = PoMe->R2_acum + tmpu32_1; | ||
+ | |||
+ | if ( (PoMe->R4_acum <= tmpu64_2)&(PoMe->R2_acum <= tmpu32_2)&(overflow_F_ == 0) ){ // Переполнения нет | ||
+ | PoMe->R4_acum = tmpu64_2; | ||
+ | PoMe->R2_acum = tmpu32_2; | ||
+ | PoMe->acum_counter++; | ||
+ | }else if ( (tmpu64_1 > PoMe->R4_acum)||(tmpu32_1 > PoMe->R2_acum)||(overflow_F_ == 0) ){ | ||
+ | // impossible, if PoMe_sum_counter_max, U2_SHIFT and max[threshold] are correct | ||
+ | overflow_F_ = 1; | ||
+ | PoMe->R4_acum = tmpu64_1; // А раз оно такое большое, то будем по нему и работать | ||
+ | PoMe->R2_acum = tmpu32_1; | ||
+ | PoMe->acum_counter = 1; | ||
+ | }else { // Штатное переполнение по капле: где-то что-то мы проворонили | ||
+ | overflow_F_ = 1; // Надеяться и ждать, что сейчас всё пучком пройдет) | ||
+ | } | ||
+ | |||
+ | // *********** Threshold setting ********************** | ||
+ | tmpu32_2 = 32 - __CLZ(tmpu32_1); // Num of ones in E[U2] | ||
+ | if ( tmpu32_2 > (PoMe_NoiseU2Bit_shifted + 8) ){ // Power >> Noise Power | ||
+ | PoMe->acum_threshold_level = 5; | ||
+ | }else if ( tmpu32_2 > (PoMe_NoiseU2Bit_shifted + 4) ){ | ||
+ | PoMe->acum_threshold_level = 4; | ||
+ | }else if ( tmpu32_2 > (PoMe_NoiseU2Bit_shifted+2) ){ | ||
+ | PoMe->acum_threshold_level = 3; | ||
+ | }else | ||
+ | if ( (PoMe->x_A2_est[0])>>(PoMe_NoiseU2Bit_shifted-1)){ | ||
+ | PoMe->acum_threshold_level = 2; | ||
+ | }else{ | ||
+ | PoMe->acum_threshold_level = 1; | ||
+ | } | ||
+ | if (PoMe->acum_counter == 1) PoMe->acum_threshold_level_first = PoMe->acum_threshold_level; | ||
+ | |||
+ | |||
+ | if ((PoMe->acum_threshold_level - PoMe->acum_threshold_level_first) > 1){ // Up | ||
+ | PoMe->acum_threshold_lock = 1; | ||
+ | SetAccumThreshold(PoMe); | ||
+ | PoMe->R4_acum = tmpu64_1; // Old data so old | ||
+ | PoMe->R2_acum = tmpu32_1; | ||
+ | PoMe->acum_counter = 1; | ||
+ | PoMe->acum_threshold_level_first = PoMe->acum_threshold_level; // One second or more | ||
+ | if (PoMe->acum_threshold_level_first > 3) | ||
+ | PoMe->acum_threshold = 1; | ||
+ | else if (PoMe->acum_threshold_level_first == 3) | ||
+ | PoMe->acum_threshold = 2; | ||
+ | else | ||
+ | PoMe->acum_threshold = 4; | ||
+ | }else if ( (PoMe->acum_threshold_level_first - PoMe->acum_threshold_level) > 1){// Down | ||
+ | if (PoMe->acum_threshold_lock == 0){ | ||
+ | PoMe->R4_acum = tmpu64_1; // Old data so old | ||
+ | PoMe->R2_acum = tmpu32_1; | ||
+ | PoMe->acum_counter = 1; | ||
+ | PoMe->acum_threshold_level_first = PoMe->acum_threshold_level; | ||
+ | PoMe->acum_threshold_lock = 1; | ||
+ | PoMe->acum_threshold = (1024 / PoMe_sum_counter_max); // One second | ||
+ | } | ||
+ | }else | ||
+ | if ( (PoMe->acum_threshold_lock == 0) & (PoMe->acum_counter == 1) ) | ||
+ | SetAccumThreshold(PoMe); | ||
+ | PoMe->acum_threshold=8; // @bug: ВРЕМЕННО | ||
+ | |||
+ | if ( (PoMe->acum_counter >= PoMe->acum_threshold) // Превысили порог накопления для текущего qcno | ||
+ | || (overflow_F_) // Overflow in R2_acum or R4_acum | ||
+ | ){ | ||
+ | PoMe->Accumulators_are_ready = PoMe->acum_counter; PoMe->acum_counter = 0; | ||
+ | PoMe->R4_acum_copy = PoMe->R4_acum; PoMe->R4_acum = 0; | ||
+ | PoMe->R2_acum_copy = PoMe->R2_acum; PoMe->R2_acum = 0; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | /** | ||
+ | Позволяет установить оценку дисперсии (мощности шумовой составляющей) корреляционных сумм и | ||
+ | зафиксировать её. | ||
+ | @param PoMe - указатель на структуру данных блока оценки с/ш | ||
+ | @param stdn2_IQ - устанавливаемое значение оценки дисперсии квадратур | ||
+ | @return 0, если прошло успешно, 1, если предлагаемое число после сдвига не влазиет в 32 разряда | ||
+ | */ | ||
+ | int SetVariancePowerMeasure(PowerMeasure_struct *PoMe, quint32 stdn2_IQ ){ | ||
+ | if (__CLZ(stdn2_IQ) >= x_stdn2_shift){ // Если предлагаемое число можно сдвинуть, не переполнив 32 разряда | ||
+ | PoMe->x_stdn2_est = stdn2_IQ; | ||
+ | // В случае увеличения порядка фильтра добавить сюда PoMe->x_stdn2_extr = stdn2_IQ; | ||
+ | PoMe->x_stdn2_est_shifted = stdn2_IQ<<x_stdn2_shift; | ||
+ | return 0; | ||
+ | }else return 1; | ||
+ | } | ||
+ | |||
+ | |||
+ | /** | ||
+ | Разрешает работу фильтру дисперсии квадратру, сбрасывает его счетчик. | ||
+ | @param PoMe - указатель на структуру данных блока оценки с/ш | ||
+ | */ | ||
+ | void AllowVariancePowerMeasure(PowerMeasure_struct *PoMe){ | ||
+ | PoMe->allow_stnd2_est = 1; | ||
+ | PoMe->start_counter = 0; | ||
+ | } | ||
+ | |||
+ | |||
+ | #if (RECEIVER_TYPE == RECEIVER_ALPACA) | ||
+ | /** | ||
+ | Возвращает число подряд идущих нулевых разрядов слева в бинарном представлении 32-разрядного числа. | ||
+ | Например, для x=b'00000111 вернет 29. | ||
+ | @param x | ||
+ | */ | ||
+ | int __CLZ(int x){ | ||
+ | |||
+ | int i; | ||
+ | |||
+ | for (i=31; i>=0; i--){ | ||
+ | if (x >> i) | ||
+ | return (31 - i); | ||
+ | } | ||
+ | return 32; | ||
+ | } | ||
+ | #endif | ||
+ | |||
+ | |||
+ | #if (RECEIVER_TYPE == RECEIVER_ALPACA) | ||
+ | #define sh_sqrt 10 | ||
+ | #else | ||
+ | static const int sh_sqrt=10; // Смещение вывода функции fix_sqrt | ||
+ | #endif | ||
+ | /** | ||
+ | Нормирует 1.0 <= x <=4.0 * (2** -sh_sqrt) . | ||
+ | @param x - нормируемое число | ||
+ | @param exp - указатель, через который возвращается сдвиг | ||
+ | @return Результат нормировки | ||
+ | */ | ||
+ | quint32 norm_x_PoMe(quint32 x, qint32 * exp){ | ||
+ | *exp =0; | ||
+ | int razr=32-__CLZ(x); | ||
+ | // printf("razr = %d \n", razr); | ||
+ | if(razr<sh_sqrt){ | ||
+ | x=x<<(sh_sqrt-razr); | ||
+ | *exp=-(sh_sqrt-razr); | ||
+ | // printf("razr < exp = %d; x = %d \n", *exp, x); | ||
+ | } | ||
+ | else if(razr > (sh_sqrt+1)){ | ||
+ | x=x>>(razr-sh_sqrt); | ||
+ | *exp=razr-sh_sqrt; | ||
+ | // printf("razr > exp = %d; x = %d \n", *exp, x); | ||
+ | } | ||
+ | if( (*exp) & 1){ | ||
+ | x=x<<1; | ||
+ | (*exp)--; | ||
+ | // printf("exp not even exp = %d; x = %d \n", *exp, x); | ||
+ | } | ||
+ | return x; | ||
+ | } | ||
+ | |||
+ | #if (RECEIVER_TYPE == RECEIVER_ALPACA) | ||
+ | #define K_sqrt1 (qint32)(0.09977*(1<<sh_sqrt)+0.5) | ||
+ | #define K_sqrt2 (qint32)(0.71035*(1<<sh_sqrt)+0.5) | ||
+ | #define K_sqrt3 (qint32)(0.3866*(1<<sh_sqrt)+0.5) | ||
+ | #else | ||
+ | static const qint32 K_sqrt1 = (qint32)(0.09977*(1<<sh_sqrt)+0.5); | ||
+ | static const qint32 K_sqrt2 = (qint32)(0.71035*(1<<sh_sqrt)+0.5); | ||
+ | static const qint32 K_sqrt3 = (qint32)(0.3866*(1<<sh_sqrt)+0.5); | ||
+ | #endif | ||
+ | //#define sqrt_27_bit | ||
+ | /** | ||
+ | Целочисленный алгорит вычисления корня \f$ y = \sqrt{x} \f$. | ||
+ | ** алгоритм с плав. зап. взят IAR\ARM\src\lib\dlib\xxsqrt.h | ||
+ | ** для sh_sqrt=10 погрешность sqrt( 0 < x < 4) не более 0.004 | ||
+ | ** для sh_sqrt=12 погрешность sqrt( 0 < x < 4) не более 0.001 | ||
+ | @param x - целое положительное число, из которого вычисляется корень | ||
+ | @return Результат вычисления корня | ||
+ | */ | ||
+ | quint32 sqrt_PoMe(quint32 x){ // x - с ц.р. = 2**-sh_sqrt | ||
+ | int exp; | ||
+ | x = norm_x_PoMe(x,&exp); // нормировка 1.0<= x <=4.0 для сходимости, exp кратна 2 | ||
+ | int y1; | ||
+ | y1 =( ( (K_sqrt2 - ((K_sqrt1*x)>>sh_sqrt)) * x ) >> sh_sqrt ) + K_sqrt3; | ||
+ | exp=exp/2-sh_sqrt/2; | ||
+ | if (exp>0) return y1<<exp; | ||
+ | else return y1>>(-exp); | ||
+ | } | ||
+ | |||
+ | |||
+ | const quint16 Power2[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}; | ||
+ | const quint16 SizePower2 = 13; | ||
+ | /** | ||
+ | Функция нахождения ближайшего большего или равного числа, являющегося степенью двойки. | ||
+ | @todo Перейти на __CLZ | ||
+ | @param x | ||
+ | @return Степень, в которую требуется возвести 2, чтоб получить искомое число | ||
+ | */ | ||
+ | quint32 NearestPower2(quint32 x){//// Ближайшее большее или равное x число 2^n (возвращаем n) | ||
+ | int i; | ||
+ | if (x >= Power2[SizePower2-1]) return SizePower2-1; // Граничные условия | ||
+ | for (i=0; i<SizePower2; i++){ | ||
+ | if (x <= Power2[i]) // Первое число в последовательности, которое привысит или будет равно x | ||
+ | return i; // и будет ответом | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | </source> | ||
+ | </div> | ||
+ | </div> | ||
+ | |||
+ | <br /> | ||
+ | <div class="NavFrame collapsed"> | ||
+ | <div class="NavHead">PowerMeasure.h</div> | ||
+ | <div class="NavContent"> | ||
+ | <source lang="c"> | ||
+ | #ifndef POWERMEASURE_H_ | ||
+ | #define POWERMEASURE_H_ | ||
+ | |||
+ | #ifndef RECEIVER_ALPACA | ||
+ | #define RECEIVER_ALPACA 1 // Альпака | ||
+ | #endif | ||
+ | #ifndef RECEIVER_NIIKP_ARM | ||
+ | #define RECEIVER_NIIKP_ARM 2 // НИИ КП'шный проект | ||
+ | #endif | ||
+ | #ifndef RECEIVER_TYPE | ||
+ | #define RECEIVER_TYPE RECEIVER_NIIKP_ARM | ||
+ | #endif | ||
+ | |||
+ | |||
+ | #include "types.h" // Определяет типы переменных q* | ||
+ | |||
+ | /** Структура данных блока измерения эквивалентного отношения сигнал/шум | ||
+ | для одного корреляционного канала. */ | ||
+ | typedef struct { | ||
+ | |||
+ | quint32 x_A2_est[1]; ///< Вектор состояния Ф СС за квадратом амплитуды КК, оценка=экстраполяция | ||
+ | quint32 x_A_est; ///< Оценка амплитуды | ||
+ | |||
+ | quint32 x_stdn2_est; ///< Оценка дисперсии КК | ||
+ | quint32 x_stdn2_est_shifted; ///< Вектор состояния Ф СС за дисперсией КК, оценка=экстраполяция, сдвинут влево | ||
+ | |||
+ | /** @name Аккумуляторы и их триггеры */ | ||
+ | quint32 R2; ///< Первичный акк. \f$ I^2 + Q^2 \f$ | ||
+ | quint64 R4; ///< Первичный акк. \f$ (I^2 + Q^2)^2 \f$ | ||
+ | |||
+ | quint32 R2_acum; ///< Вторичный аккумулятор R2 | ||
+ | quint64 R4_acum; ///< Вторичный аккумулятор R4 | ||
+ | |||
+ | quint32 R2_acum_copy; ///< Триггер R2_acum | ||
+ | quint64 R4_acum_copy; ///< Триггер R4_acum | ||
+ | //@} | ||
+ | |||
+ | /** @name Счетчики для аккумуляторов */ | ||
+ | quint16 sum_counter; ///< для R2, R4 | ||
+ | quint16 acum_counter; ///< для R2_acum, R4_acum | ||
+ | //@} | ||
+ | |||
+ | /** @name Пороги накоплений R2_acum, R4_acum */ | ||
+ | quint16 acum_threshold; | ||
+ | quint16 acum_threshold_lock; | ||
+ | qint16 acum_threshold_level; | ||
+ | qint16 acum_threshold_level_first; | ||
+ | //@} | ||
+ | |||
+ | quint16 fail_counter; ///< Число подряд идущих срывов измерения амплитуды (комплексные корни) | ||
+ | |||
+ | quint32 start_counter; ///< Счетчик тактов от начала включения блока | ||
+ | |||
+ | quint8 allow_stnd2_est; ///< Разрешить оценивать и фильтровать дисперсию квадратур | ||
+ | |||
+ | int Accumulators_are_ready; ///< Флаг готовности триггеров R2_acum_copy, R4_acum_copy и копия счетчика в одном лице | ||
+ | |||
+ | #if (RECEIVER_TYPE == RECEIVER_ALPACA) | ||
+ | /** @name Сохраненные измерения, поступающие на вход фильтров */ | ||
+ | quint32 SQ_A_izm; ///< Квадрата амплитуды | ||
+ | quint32 SQ_stdn_izm; ///< Квадрата СКО | ||
+ | //@} | ||
+ | quint32 qcno; ///< Оценка отношения с/ш, в абсолютных единицах | ||
+ | double qcno_dBHz; ///< Оценка отношения с/ш, в дБГц | ||
+ | double qcno_dBHz_extr; ///< Экстраполяция на следующий такт отношения с/ш, в дБГц | ||
+ | #endif | ||
+ | |||
+ | quint32 IQ_Power; ///< Оценка \f$ E[I^2 + Q^2] \f$ | ||
+ | |||
+ | } PowerMeasure_struct; | ||
+ | |||
+ | |||
+ | #if (RECEIVER_TYPE == RECEIVER_ALPACA) | ||
+ | #define PoMe_sum_counter_max 128 ///< Число суммирований в аккумуляторах R2, R4 | ||
+ | #define PoMe_obr_Kf_stdn_0 256 ///< Обратный коэффициент Ф СС за дисперсией КК | ||
+ | |||
+ | /** | ||
+ | I,Q in signed short => | ||
+ | - log2((2^15)^2 * 2 / 2^6 * 128) = 32 | ||
+ | - log2((2^15)^4 * 2 / 2^6 * 128) = 64 | ||
+ | |||
+ | U2_SHIFT <-> : | ||
+ | - 1) log2(max U^2 >> U2_SHIFT) < 32 | ||
+ | - 2) log2(max U^4 >> U2_SHIFT) < 64 | ||
+ | - 3) PoMe_sum_counter_max < max_acum_counter (if hasn't reserve in 1) and 2) ) | ||
+ | - 4) min U^2 >> U2_SHIFT > 0 | ||
+ | |||
+ | Estimates of stdn2 and A2 are shifted by U2_SHIFT relative real values. | ||
+ | */ | ||
+ | #define U2_SHIFT 6 ///< Сдвиг I^2+Q^2 перед аккумулированием | ||
+ | |||
+ | #define PoMe_NoiseU2Bit (20) ///< Typical \f$ \log_2(Noise^2) \f$, exponent of two | ||
+ | #define PoMe_NoiseU2Bit_shifted (PoMe_NoiseU2Bit-U2_SHIFT) ///< PoMe_NoiseU2Bit-U2_SHIFT | ||
+ | #define x_stdn2_shift = (8); ///< Сдвиг дисперсии квадратур во внутренней структуре фильтра | ||
+ | |||
+ | /** @name Делитель вторичных аккумуляторов для каждого времени накопления, сдвиги */ | ||
+ | #define PoMe_Threshold_5_sh 1 // Период: 2*PoMe_sum_counter_max | ||
+ | #define PoMe_Threshold_4_sh 2 // 4*PoMe_sum_counter_max | ||
+ | #define PoMe_Threshold_3_sh 3 // 8*PoMe_sum_counter_max | ||
+ | #define PoMe_Threshold_2_sh 5 // 32*PoMe_sum_counter_max | ||
+ | #define PoMe_Threshold_1_sh 6 // 64*PoMe_sum_counter_max | ||
+ | #define PoMe_Threshold_def_sh 5 // 32*PoMe_sum_counter_max | ||
+ | //@} | ||
+ | |||
+ | /** @name Делитель вторичных аккумуляторов для каждого времени накопления */ | ||
+ | #define PoMe_Threshold_5 (1<<PoMe_Threshold_5_sh) | ||
+ | #define PoMe_Threshold_4 (1<<PoMe_Threshold_4_sh) | ||
+ | #define PoMe_Threshold_3 (1<<PoMe_Threshold_3_sh) | ||
+ | #define PoMe_Threshold_2 (1<<PoMe_Threshold_2_sh) | ||
+ | #define PoMe_Threshold_1 (1<<PoMe_Threshold_1_sh) | ||
+ | #define PoMe_Threshold_def (1<<PoMe_Threshold_def_sh) | ||
+ | //@} | ||
+ | |||
+ | #define PoMe_Tcorr 0.001 ///< For qcno_dBHz calculation - длительность одного такта Ф | ||
+ | |||
+ | /** "Число лидирующих нулей" - число первых нулей бинарного представления. | ||
+ | Данная функция реализована рекурсивно для совместимости с ARM НИИ КП | ||
+ | @param x Входное 32-разрядное число | ||
+ | @return Число первых нулей бинарного представления переменной */ | ||
+ | int __CLZ(int x); | ||
+ | |||
+ | #else if (RECEIVER_TYPE == RECEIVER_NIIKP_ARM) /*#ifndef NIIKP_ARM_F_*/ | ||
+ | |||
+ | const int exp_kARU = 12; ///< Экспонента для переменной kARU ~ обратной крутизны | ||
+ | const int PoMe_sum_counter_max = 128; ///< Число суммирований в аккумуляторах R2, R4 | ||
+ | const int PoMe_obr_Kf_stdn_0 = 256; ///< Обратный коэффициент Ф СС за дисперсией КК | ||
+ | const quint16 max_fail_counter = 2; ///< Число разрешенных fail_counter до снятия канала | ||
+ | |||
+ | /** | ||
+ | I,Q in signed short => | ||
+ | - log2((2^15)^2 * 2 / 2^6 * 128) = 32 | ||
+ | - log2((2^15)^4 * 2 / 2^6 * 128) = 64 | ||
+ | |||
+ | U2_SHIFT <-> : | ||
+ | - 1) log2(max U^2 >> U2_SHIFT) < 32 | ||
+ | - 2) log2(max U^4 >> U2_SHIFT) < 64 | ||
+ | - 3) PoMe_sum_counter_max < max_acum_counter (if hasn't reserve in 1) and 2) ) | ||
+ | - 4) min U^2 >> U2_SHIFT > 0 | ||
+ | |||
+ | Estimates of stdn2 and A2 are shifted by U2_SHIFT relative real values. | ||
+ | */ | ||
+ | const int U2_SHIFT = 0; ///< Сдвиг I^2+Q^2 перед аккумулированием | ||
+ | |||
+ | const qint16 PoMe_NoiseU2Bit = 6; ///< Typical \f$ log_2(Noise^2)\f$, exponent of two | ||
+ | const qint16 PoMe_NoiseU2Bit_shifted = (PoMe_NoiseU2Bit-U2_SHIFT); ///< PoMe_NoiseU2Bit-U2_SHIFT | ||
+ | const qint16 x_stdn2_shift = 8; ///< Сдвиг дисперсии квадратур во внутренней структуре фильтра | ||
+ | |||
+ | /** @name Делитель вторичных аккумуляторов для каждого времени накопления, сдвиги */ | ||
+ | const qint16 PoMe_Threshold_5_sh = 2; // 4 (x 128 мс) | ||
+ | const qint16 PoMe_Threshold_4_sh = 3; // 8 | ||
+ | const qint16 PoMe_Threshold_3_sh = 4; // 16 | ||
+ | const qint16 PoMe_Threshold_2_sh = 4; // 16 | ||
+ | const qint16 PoMe_Threshold_1_sh = 5; // 32 | ||
+ | const qint16 PoMe_Threshold_def_sh = 5; // 32 | ||
+ | //@} | ||
+ | |||
+ | /** @name Делитель вторичных аккумуляторов для каждого времени накопления */ | ||
+ | const qint16 PoMe_Threshold_5 = (1<<PoMe_Threshold_5_sh); | ||
+ | const qint16 PoMe_Threshold_4 = (1<<PoMe_Threshold_4_sh); | ||
+ | const qint16 PoMe_Threshold_3 = (1<<PoMe_Threshold_3_sh); | ||
+ | const qint16 PoMe_Threshold_2 = (1<<PoMe_Threshold_2_sh); | ||
+ | const qint16 PoMe_Threshold_1 = (1<<PoMe_Threshold_1_sh); | ||
+ | const qint16 PoMe_Threshold_def = (1<<PoMe_Threshold_def_sh); | ||
+ | //@} | ||
+ | |||
+ | #endif /* if (RECEIVER_TYPE == RECEIVER_NIIKP_ARM) */ | ||
+ | |||
+ | void InitPowerMeasure(PowerMeasure_struct *PoMe, quint32 Init_qcno); | ||
+ | |||
+ | void DoPowerMeasure(PowerMeasure_struct *PoMe); | ||
+ | |||
+ | void AccumPowerMeasure(PowerMeasure_struct *PoMe, quint32 U2); | ||
+ | |||
+ | int SetVariancePowerMeasure(PowerMeasure_struct *PoMe, quint32 stdn2_IQ); | ||
+ | |||
+ | void AllowVariancePowerMeasure(PowerMeasure_struct *PoMe); | ||
+ | |||
+ | #endif // POWERMEASURE_H_ | ||
+ | </source> | ||
+ | </div> | ||
+ | </div> | ||
+ | |||
+ | |||
+ | == Проблемы == | ||
+ | |||
+ | Doxygen, во всяком случае мой, некорректно работает с директивами препроцессора <code>#if, #ifdef</code> и т.п. Пока удается решить эту проблему перечислением в Doxyfile (поле PREDEFINED) значений всех используемых в таких выражениях define'ов. | ||
+ | |||
== Ссылки == | == Ссылки == |
Текущая версия на 21:40, 19 апреля 2011
Doxygen — это кроссплатформенная система документирования исходных текстов, которая поддерживает C++, Си, Objective-C, Python, Java, IDL, PHP, C#, Фортран, VHDL и, частично, D.
Doxygen генерирует документацию на основе набора исходных текстов и также может быть настроен для извлечения структуры программы из недокументированных исходных кодов. Возможно составление графов зависимостей программных объектов, диаграмм классов и исходных кодов с гиперссылками.
Doxygen имеет встроенную поддержку генерации документации в формате HTML, LaTeX, man, RTF и XML. Также вывод может быть легко сконвертирован в CHM, PostScript, PDF.
Для html-представления документации, размещаемого на web-серверах, существует удобный способ организации поиска (при помощи создаваемого Doxygen'ом PHP-модуля) и ссылок на внешнюю документацию.
Doxygen - консольная программа в духе классической Unix. Она работает подобно компилятору, анализируя исходные тексты и создавая документацию.
Содержание |
[править] Что требуется установить для полноценной работы
[править] Doxygen
Основная программа
[править] Graphiz
Graphviz – это свободно распространяемый пакет утилит для визуализации данных. Нам он нужен для того, чтобы Doxygen мог показать в документации отношения наследования, графы вызовов и прочую информацию в виде наглядных изображений.
[править] LaTeX
При установленном пакете того или иного LaTeX-дистрибутива, Doxygen конвертирует TeX-разметку в комментариях в изображения, а затем вставляет их в итоговый отчет. Также генерирует TeX-файлы, а затем PDF.
[править] Doxywizard
Параметры создания документации читаются из конфигурационного файла, имеющего простой текстовый формат (см. ниже). Для упрощения манипуляций с конфигурационным файлом (а он содержит довольно много настроек), существует несколько утилит с графическим интерфейсом. Одна из них, doxywizard, поставляется вместе с Doxygen.
# Весь текст после символа (#) считается комментарием и будет проигнорирован.
# Формат:
# TAG = value [value, ...]
# Для списка итемов может использоваться расширение:
# TAG += value [value, ...]
# Значение содержащее пробелы должно быть заключено в кавычки (" ")
#---------------------------------------------------------------------------
# Проектно зависимые опции конфигурации (связанные с конкретным проектом)
#---------------------------------------------------------------------------
#1. Этот тег определяет кодировку используемую для всех символов в этом конфигурационном файле.
# По умолчанию это UTF-8 которая также используется для всего текста перед первым вхождением этого тега.
# Doxygen использует libiconv (или iconv встроеную в libc) для перекодирования. Список доступных кодировок http://www.gnu.org/software/libiconv.
DOXYFILE_ENCODING = UTF-8
#2. PROJECT_NAME тег значением которого является единое слово (или последовательность слов окруженная кавычками) которое будет идентифицировать проект.
PROJECT_NAME = testProject
# 3.PROJECT_NUMBER значение тега (если оно указано) будет входить в наименование проекта (например номер ревизии).
# Это может быть удобно для архивирования генерируемой документации или
# если используется система контроля версий.
PROJECT_NUMBER = 1.0
# 4. OUTPUT_DIRECTORY тег используется для указания (относительного или абсолютного)
# начального пути для размещения генерируемой документации.
# Если введены относительные пути, то это будет считаться относительно размещения
# каталога в котором будет запущена утилита doxygen. Если значение пустое, то будет использована текущая директория.
OUTPUT_DIRECTORY =
# 5. Если CREATE_SUBDIRS тег установлен в YES, тогда doxygen будет создавать
# 4096 подкаталогов (по 2 уровня) для выходных каталогов для каждого выходного
# формата и будет распределять генерируемые файлы в этих каталогах.
# Включение этой опции может быть полезно когда на входе doxygen огромное количество
# исходных файлов, и тогда раскладывание всех генерируемых файлов в некотором одном каталоге
# может привести к характерным проблемам файловой системы.
CREATE_SUBDIRS = NO
# 6. OUTPUT_LANGUAGE тег используется для указания языка в котором пишется вся
# документация генерируемая doxygen. Doxygen будет использовать эту
# информацию для генерации всего константного вывода в собственный язык.
# По умолчанию язык English, другие поддерживаемые языки:
# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
OUTPUT_LANGUAGE = Russian
# 7. Если BRIEF_MEMBER_DESC тег установлен в YES (по умолчанию) Doxygen будет
# включать краткое описание членов после членов которые указаны в
# file и class документации (подобно JavaDoc).
# Значение NO отключает это.
BRIEF_MEMBER_DESC = YES
# 8. Если REPEAT_BRIEF тег установлен в YES (по умолчанию) Doxygen будет добавлять
# краткое описание членов функций перед детальным описанием.
# Примечание: если оба тега HIDE_UNDOC_MEMBERS и BRIEF_MEMBER_DESC установлены в NO,
# то краткая документация будет полностью скрыта.
REPEAT_BRIEF = YES
# 9. Этот тег реализует квази-интеллигентные краткие описания аббревиатуры
# которые используются для формирования текстов в различных листингах. Каждая строка
# в этом листе, которая является начальным текстом краткого описания, будет
# выкинута из текста и результат после обработки всего списка, будет использован
# как текст аннотации. Иначе краткое описание будет использовано "как есть".
# При пустом значении, используются следующие значения ("$name" автоматически
# заменяется именем сущности): "$name class" "$name widget"
# "The $name file" "is" "provides" "specifies" "contains"
# "represents" "a" "an" "the".
ABBREVIATE_BRIEF =
# 10. Если ALWAYS_DETAILED_SEC и REPEAT_BRIEF теги оба установлены в YES тогда
# Doxygen будет генерировать подробные секции даже если там только краткое
# описание.
ALWAYS_DETAILED_SEC = NO
# 11. Если INLINE_INHERITED_MEMB тег установлен в YES, doxygen будет показывать все
# наследованные члены класса в документации этого класса как если бы эти члены
# были обычными членами класса. Конструкторы, деструкторы и связанные
# операторы базовых классов не будут показаны.
INLINE_INHERITED_MEMB = NO
# 12. Если FULL_PATH_NAMES тег установлен в YES тогда Doxygen будет указывать полный
# путь перед каждым именем файла в списке файлов и в заголовочных файлах.
# Если установлено NO то будут использованы кратчайшие имена файлов, которые должны быть уникальны.
FULL_PATH_NAMES = YES
# 13. Если FULL_PATH_NAMES тег установлен в YES тогда STRIP_FROM_PATH тег
# может быть использован для очистки части пути определенной пользователем. Очистка (урезание)
# будет производиться только если одна из указанных строк соответствует левой части пути. Тег может быть использован для показа относительных путей
# в списке файлов.
# Если значение пустое (не указано) то каталог из которого запущен doxygen используется как базовый для урезания путей.
STRIP_FROM_PATH =
# 14. STRIP_FROM_INC_PATH тег может быть использован для урезания определенной пользователем части
# пути к файлам подключаемым директивой #include<>.
# Если тег пустой то используется только имя заголовочного файла содержащее объявленный класс.
# Иначе должны быть определены пути поиска заголовочных файлов,
# которые передаются компилятору через флаг -I.
STRIP_FROM_INC_PATH =
# 15. Если SHORT_NAMES тег установлен в YES, doxygen будет генерировать наиболее короткую
# (но менее читабельные) имена файлов. Это может быть полезно если ваша файловая система
# не поддерживает длинных имен, например в случае DOS, Mac, или CD-ROM.
SHORT_NAMES = NO
# 16. Если JAVADOC_AUTOBRIEF тег установлен в YES тогда Doxygen
# будет интерпретировать первую строку (до первой точки) в JavaDoc-стиле
# как комментарий краткого описания (краткий комментарий). Если установлен в NO, то JavaDoc
# комментарий будет считаться подобным комментарию в Qt-стиле
# (это требует явного указания текста команды @brief для краткого описания.)
JAVADOC_AUTOBRIEF = NO
# 17. Если QT_AUTOBRIEF тег установлен в YES тогда Doxygen будет
# интерпретировать первую строку (до первой точки) из комментария в Qt-стиле
# как краткое описание. Если установлен в NO, то комментарии
# будут восприниматься как обычные комментарии в Qt-стиле (это требует
# явного указания команды \brief для краткого описания.)
QT_AUTOBRIEF = NO
# 18. MULTILINE_CPP_IS_BRIEF тег установленный в YES заставит Doxygen
# обработать многострочный C++ блок специального комментария (то есть блок из //! или ///
# комментариев) как краткое описание. Такое поведение по умолчанию.
# Новым поведением по умолчанию является обработка многострочных C++ блочных комментариев как подробного описания.
# Установите этот тег в YES если вы предпочитаете старое поведение.
MULTILINE_CPP_IS_BRIEF = NO
# 19. Если DETAILS_AT_TOP тег установлен в YES тогда Doxygen
# будет выводить детализированное описание вблизи верха документации, подобно JavaDoc.
# Если установить в NO, то подробное описание появляется после членов функции.
DETAILS_AT_TOP = NO
# 20. Если INHERIT_DOCS тег установлен в YES (по умолчанию) тогда незадокументированные
# члены наследуют документацию от любого задокументированного члена который они переопределяют.
INHERIT_DOCS = YES
# 21. Если SEPARATE_MEMBER_PAGES тег установлен в YES, тогда doxygen будет создавать
# новую страницу для каждого члена. Если установлен в NO, то документация на элементы-члены будет
# частью файла/класса/пространства_имён которые их содержат.
SEPARATE_MEMBER_PAGES = NO
# 22. TAB_SIZE тег может быть использован для установки количества пробелов в табе.
# Doxygen использует это значение для замены табов на пробелы в фрагментах кода.
TAB_SIZE = 8
# 23. Этот тег может быть использован для задания количества псевдонимов которые работают как команды
# в документации. Псевдоним имеет вид "name=value".
# Например добавление "sideeffect=\par Side Effects:\n" позволяет
# ввести команду \sideeffect (или @sideeffect) в документацию, которая
# в результате будет преобразована в определенный пользователем параграф с заголовком "Side Effects:".
# Можно также указывать последовательность \n в составе значения псевдонима, которая будет преобразована в символ новой строки.
ALIASES =
# 24. Установка тега OPTIMIZE_OUTPUT_FOR_C в YES если проект содержит исходный код только на C
# Doxygen будет генерировать документацию более подходящую для C.
# Например, некоторые используемые имена будут различаться. Список
# всех членов будет исключен из вывода, и т.д.
OPTIMIZE_OUTPUT_FOR_C = NO
# 25. Устанавливайте OPTIMIZE_OUTPUT_JAVA тега в YES если ваш проект содержит только исходники на Java.
# Doxygen тогда будет генерировать вывод который более предназначен для Java.
# Например, пространства имен (namespace) будут представлены как пакеты (packages), представленная квалификация
# будет выглядеть по разному.
OPTIMIZE_OUTPUT_JAVA = NO
# 26. Если вы используете классы STL (то есть std::string, std::vector, и т.д.) но не желаете
# включать (используя тег file) STL исходники как входные данные, тогда вы должны установить этот тег
# в значение YES чтобы позволить doxygen правильно обрабатывать соответствующие объявления и определения функций
# у которых аргументы содержат переменные типа STL классов (func(std::string); v.s.
# func(std::string) {}). Это позволяет делать наследование и сотрудничество
# диаграмм которые обертывают STL классы более завершенно и точно.
BUILTIN_STL_SUPPORT = NO
# 27. Если вы используете Microsoft-овский C++/CLI язык, вы должны установить опцию в YES для
# включения поддержки анализа.
CPP_CLI_SUPPORT = NO
# 28. Если в документации используется группировка членов и DISTRIBUTE_GROUP_DOC
# тег установлен в YES, тогда doxygen будет многократно использовать документирование первого
# члена в группе (или любого) для других членов группы. По умолчанию
# все члены группы должны быть задокументированы явно.
DISTRIBUTE_GROUP_DOC = NO
# 29. Установка SUBGROUPING тега в YES (по умолчанию) допускает группировку членов класса
# некоторого типа (например группировку публичных функций) вместе в одну
# подгруппу некоторого типа (например секцию Public Functions). Установка этого тега в
# NO предотвращает подгруппировку. Как альтернатива, это может быть определено только для некоторых классов используя
# команду \nosubgrouping.
SUBGROUPING = YES
#---------------------------------------------------------------------------
# Опции конфигурации связанные с построением
#---------------------------------------------------------------------------
# 30. Если EXTRACT_ALL тег установлен в YES doxygen будет принимать все сущности в
# документации как задокументированные, даже если они были непригодны для документирования.
# Приватные члены класса и статические члены класса будут скрытыми без
# EXTRACT_PRIVATE и EXTRACT_STATIC тегов установленных в YES
EXTRACT_ALL = NO
# 31. Если EXTRACT_PRIVATE тег установлен в YES все частные члены класса
# будут включены в документацию.
EXTRACT_PRIVATE = NO
# 32. Если EXTRACT_STATIC тег установлен в YES все статические переменные
# будут включены в документацию.
EXTRACT_STATIC = NO
# 33. Если EXTRACT_LOCAL_CLASSES тег установлен в YES то классы (и структуры)
# объявленные локально в исходных файлах будут включены в документацию.
# Если установлен в NO то в документацию будут включены только классы содержащиеся в заголовочных файлах.
EXTRACT_LOCAL_CLASSES = YES
# 34. Этот флаг полезен только для Objective-C кода. Когда он установлен в YES то локальные
# методы, которые объявлены в секции реализации но не в интерфейсной части
# будут задокументированы.
# если установлен в NO (по умолчанию) только методы интерфейсной части будут включены в документацию.
EXTRACT_LOCAL_METHODS = NO
# 35. Если этот флаг установлен в YES, члены анонимных (неизвестных) пространств имен будут извлекаться и
# показываться в документации как в пространстве имен 'anonymous_namespace{file}',
# где file будет заменено на базовое (короткое) имя файла в котором содержится это пространство имен.
# По умолчанию неизвестные пространства имен скрыты.
EXTRACT_ANON_NSPACES = NO
# 36. Если HIDE_UNDOC_MEMBERS тег установлен в YES, Doxygen будет скрывать все
# недокументируемые члены документируемых классов, файлов и пространств имен.
# Если установлен в NO (по умолчанию) то эти члены будут включены в
# различные обзоры, но отдельная секция документации не будет создана.
# Эта секция не работает, если EXTRACT_ALL установлена в YES.
HIDE_UNDOC_MEMBERS = NO
# 37. Если HIDE_UNDOC_CLASSES установлен в YES, Doxygen будет скрывать все
# недокументируемые классы которые нормально видятся в классовой иерархии.
# Если установлено в NO (по умолчанию) эти классы будут включаться в различные
# обзоры. Эта опция не работает, если EXTRACT_ALL установлена в YES.
HIDE_UNDOC_CLASSES = NO
# 38. Если HIDE_FRIEND_COMPOUNDS тег установлен в YES, Doxygen будет скрывать все
# дружеские объявления friend (class|struct|union).
# Если установлено в NO (по умолчанию) то эти объявления будут включены в документацию.
HIDE_FRIEND_COMPOUNDS = NO
# 39. Если HIDE_IN_BODY_DOCS тег установлен в YES, Doxygen будет прятать любые
# блоки документации найденные внутри тела функции.
# Если установлено в NO (по умолчанию) то эти блоки будут добавляться в
# блок документации в детальным описанием функции.
HIDE_IN_BODY_DOCS = NO
# 40. INTERNAL_DOCS тег определяет необходимость включения в документацию комментариев
# которые введены после команды \internal. Если тег установлен
# в NO (по умолчанию) тогда такая документация не будет включена.
# Установка в YES подключает внутреннюю документацию.
INTERNAL_DOCS = NO
# 41. Если CASE_SENSE_NAMES тег установлен в NO то Doxygen будет генерировать
# файловые имена только в нижнем регистре символов. Если установлено в YES то символы верхнего регистра также
# доступны. Это полезно если у вас есть классы или файлы имена которых различаются только регистром
# в случае если ваша файловая система поддерживает регистрозависимые имена. Пользователям Windows
# и Mac рекомендуется установить эту опцию в NO.
CASE_SENSE_NAMES = YES
# 42. Если HIDE_SCOPE_NAMES тег установлен в NO (по умолчанию) тогда Doxygen
# будет записывать в документацию элементы с их полной спецификацией включающей имя класса или пространство имен.
# Если тег установлен в YES то принадлежность элемента будет скрыта.
HIDE_SCOPE_NAMES = NO
# 43. Если SHOW_INCLUDE_FILES тег установлен в YES (по умолчанию) тогда Doxygen
# будет составлять список файлов которые включаются из файла в документацию этого файла.
SHOW_INCLUDE_FILES = YES
# 44. Если INLINE_INFO тег установлен в YES (по умолчанию) тогда тег [inline]
# всталяется в документацию для пометки inline элементов.
INLINE_INFO = YES
# 45. Если SORT_MEMBER_DOCS тег установлен в YES (по умолчанию) тогда doxygen
# будет сортировать (подробную) документацию по файлу и члены класса
# в алфавитном порядке по именам членов. Если тег установлен в NO то члены будут располагаться в порядке объявления.
SORT_MEMBER_DOCS = YES
# 46. Если SORT_BRIEF_DOCS тег установлен в YES то doxygen будет сортировать
# краткую информацию по элементам, пространствам имен и членам классов в алфавитном порядке
# по именам членов. Если тег установлен в NO (по умолчанию) то элементы будут располагаться в порядке объявления.
SORT_BRIEF_DOCS = NO
# 47. Если SORT_BY_SCOPE_NAME тег установлен в YES, список классов будет
# отсортирован по полноквалифицированным именам, включая пространства имен. Если установлен в
# NO (по умолчанию), то список классов будет отсортирован только по именам классов,
# исключая наименования пространств имен.
# Примечание: Эта опция не очень полезна если HIDE_SCOPE_NAMES установлен в YES.
# Примечание: Эта опция применяется только к списку классов, не в алфавитном списке.
SORT_BY_SCOPE_NAME = NO
# 48. GENERATE_TODOLIST тег может быть использован для включения (YES) или
# исключения (NO) списка доработок в документацию. Этот список создается извлечением информации из \todo
# команд в документации.
GENERATE_TODOLIST = YES
# 49. GENERATE_TESTLIST тег может быть использован для включения (YES) или
# отключения (NO) списка тестов. Этот список создается выборкой информации из \test
# команд в документации.
GENERATE_TESTLIST = YES
# 50. GENERATE_BUGLIST тег может быть использован для включения (YES) или
# исключения (NO) списка багов. Этот список создается выборкой информации из \bug
# команд в документации.
GENERATE_BUGLIST = YES
# 51. GENERATE_DEPRECATEDLIST тег может быть использован для включения (YES) или
# исключения (NO) списка возражений. Этот список создается путем извлечения информации
# из \deprecated команд в документации.
GENERATE_DEPRECATEDLIST= YES
# 52. The ENABLED_SECTIONS тег может быть использован для указания имен секций в условных
# конструкциях которые подлежат включению в документацию, помеченных как \if sectionname ... \endif.
ENABLED_SECTIONS =
# 53. MAX_INITIALIZER_LINES тег определяет максимальное количество строк
# из которого состоит начальное значение переменной или объявления consists, которые можно включать
# в документацию. Если инициализатор состоит из большего количества линий тогда он будет скрыт.
# Используя значение 0 можно спрятать все инициализаторы целиком.
# Для включения инициализаторов индивидуальных переменных или объявлений в
# документацию может управляться использованием \showinitializer или \hideinitializer
# команды в документации, и не обращая внимания на эту настройку.
MAX_INITIALIZER_LINES = 30
# 54. Установка SHOW_USED_FILES тега в NO отключает список файлов генерируемых
# внизу документации классов и структур. Если она установлена в YES то
# в списке будет упоминание файлов которые были использованы для генерации документации.
SHOW_USED_FILES = YES
# 55. Если в исходниках проекта размещается множество каталогов
# тогда настройка SHOW_DIRECTORIES тега в YES будет иерархично показывать каталоги в документации.
# По умолчанию NO.
SHOW_DIRECTORIES = NO
# 56. FILE_VERSION_FILTER тег может быть использован для указания программы или скрипта который
# doxygen будет вызывать для получения текущей версии каждого файла (обычно из
# системы управления версиями). Doxygen быдет вызывать программу. исполняя (через
# popen()) the команду <command> <input-file>, где <command> является именем программы
# указанном в FILE_VERSION_FILTER теее, и <input-file> является именем входного файла
# поставляемое doxygen. Всё что это программа будет писать в стандартный вывод
# будет рассматриваться как имя файла. Смотрите руководство к программе для получения нужных сведений.
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# Опции конфигурации относящиеся к предупреждающим сообщениям и сообщениям о степени выполнения
#---------------------------------------------------------------------------
# 57. QUIET тег может быть использован для включения/выключения сообщений генерируемых
# doxygen. Возможные значения YES и NO. Если пусто, то используется NO.
QUIET = NO
# 58. WARNINGS тег может быть использован для включения/отключения предупреждающих сообщений которые
# генерируются doxygen. Возможные значения YES и NO. Если значение пустое,
# то используется NO.
WARNINGS = YES
# 59. Если WARN_IF_UNDOCUMENTED установлен в YES, тогда doxygen будет генерировать предупреждения
# для недокументируемых элементов. Если EXTRACT_ALL установлен в YES тогда этот флаг будет
# автоматически отключен.
WARN_IF_UNDOCUMENTED = YES
# 60. Если WARN_IF_DOC_ERROR установлен в YES, doxygen будет генерировать предупреждения для
# потенциальных ошибок в документировании, таких как документирование некоторых
# параметров в документируемой функции, или документируются параметры которые
# не существуют или используется ошибочные команды разметки.
WARN_IF_DOC_ERROR = YES
# 61. Эта WARN_NO_PARAMDOC опция может помочь получить предупреждения для
# функций которые документируются, но имеют не документируемые для этого параметры
# или возвращаемое значение. Если установить в NO (по умолчанию), то doxygen будет предупреждать
# только о неправильных или незавершенных параметрах документации, но не об отсутствии
# документации.
WARN_NO_PARAMDOC = NO
# 62. WARN_FORMAT тег определяет формат предупреждающих сообщений которые
# doxygen может выбрасывать. Строки должны содержать $file, $line, и $text
# теги, которые будут заменяться именем файла и номером строки из которых
# предупреждение было порождено и сам текст предупреждения. Опционально формат может содержать
# $version, который будет заменяться версией файла (если это может
# быть получено через FILE_VERSION_FILTER)
WARN_FORMAT = "$file:$line: $text"
# 63. WARN_LOGFILE тег может быть использован для указания файла в который предупреждающие и ошибочные
# сообщения должны быть записаны. Если значение пустое то вывод пишется в stderr.
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Опции конфигурации связанные с входными файлами
#---------------------------------------------------------------------------
# 64. INPUT тег может быть использован для указания файлов и/или каталогов которые содержат
# документируемые исходные тексты. Имена файлов можно вводить подобно "myfile.cpp" или
# или каталогов подобно "/usr/src/myproject". Разделять файлы и каталоги нужно пробелами
INPUT =
# 65. Этот тег может быть использован для указания кодировки символов текстовых файлов-исходников которые
# анализируются doxygen. Во внутреннем представлении doxygen использует UTF-8 кодировку, которая также является входной кодировкой по умолчанию.
# Doxygen использует libiconv (или iconv встроенный в libc) для перекодировки.
# Смотрите http://www.gnu.org/software/libiconv для получения информации о списке возможных кодировок.
INPUT_ENCODING = UTF-8
# 66. Если значение тега INPUT содержит каталоги, то можно использовать
# FILE_PATTERNS тег для указания одного или более шаблонных карт (например *.cpp
# и *.h) для фильтрования списка исходных файлов в каталогах. Если значение пустое
# то тестируются следующие шаблоны:
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
FILE_PATTERNS =
# 67. RECURSIVE тег может использоваться для указания того нужно или нет в подкаталогах
# искать входные файлы. Возможные значения YES and NO.
# Если значение пустое, то используется NO.
RECURSIVE = NO
# 68. EXCLUDE тег может быть использован для указания файлов и/или каталогов которые должны
# быть исключены из списка входных файлов определяюемых тегом INPUT. Этот путь позволяет очень просто исключить
# подкаталоги из дерева каталогов корень которого указан в теге INPUT.
EXCLUDE =
# 69. EXCLUDE_SYMLINKS тег может быть использован для указания того допустимы или нет файлы или
# каталоги которые являются символическими ссылками (характеристика файловой системы Unix)
# то есть будут ли они исключаться из списка входных файлов.
EXCLUDE_SYMLINKS = NO
# 70. Если значение тега INPUT содержит каталоги, то можно использовать
# EXCLUDE_PATTERNS тег для определения одной или более шаблонных карт исключающих
# наборы файлов из этих каталогов. Примечательно что можно использовать шаблоны для соответствия
# против файлов с абсолютными путями, так для исключения всех тестовых каталогов можно например использовать шаблон */test/*
EXCLUDE_PATTERNS =
# 71. EXCLUDE_SYMBOLS тег может использоваться для указания одного или нескольких символьных имён
# (пространств имён, классов, функций, и т.д.) которые будут исключены из вывода.
# Символьное имя может быть полностью квалифицированным именем, словом, или шаблоном с использованием символа *,
# Примеры: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
EXCLUDE_SYMBOLS =
# 72. EXAMPLE_PATH тег может быть использован для указания одного или нескольких файлов или
# каталогов которые содержат фрагменты кода примеров необходимых для включения в документацию
# (более подробно в описание команды \include).
EXAMPLE_PATH =
# 73. Если значение тега EXAMPLE_PATH содержит каталоги, вы можете использовать
# тег EXAMPLE_PATTERNS для указания одного или нескольких шаблонов (например *.cpp
# и *.h) для фильтрации выводимых исходных файлов в каталогах. Если тег пустой
# то будут включены все файлы.
EXAMPLE_PATTERNS =
# 74. Если EXAMPLE_RECURSIVE тег установлен в YES то подкаталоги будут
# осматриваться на предмет наличия исходных файлов где использованы команды \include or \dontinclude
# несмотря на значение тега RECURSIVE.
# Возможные значения YES и NO. При пустом теге будет использовано значение NO.
EXAMPLE_RECURSIVE = NO
# 75. Тег IMAGE_PATH тег может быть использован для указания одного или нескольких файлов или
# каталогов которые содержат изображения которые будут включены в документацию
# (командой \image).
IMAGE_PATH =
# 76. INPUT_FILTER тег используется для указания программы которую doxygen должна
# вызвать для фильтрования каждого входящего файла. Doxygen будет вызывать программу фильтрации
# исполняя (через popen()) команду <filter> <input-file>, где <filter>
# есть значение INPUT_FILTER тега, и <input-file> есть имя
# входного файла. Doxygen будет использовать выходную информацию которую фильтрующая команда
# пишет в стандартный вывод. Если FILTER_PATTERNS определён, то этот тег будет игнорироваться.
INPUT_FILTER =
# 77. FILTER_PATTERNS тег используется для указания фильтров на каждый файловый
# шаблон. Doxygen будет сравнивать файловое имя с каждым шаблоном и применять
# фильтр если существует соответствие. Пример формирования списка фильтров:
# pattern=filter (подобно *.cpp=my_cpp_filter). Смотрите INPUT_FILTER для дополнительной
# информации о том как используются фильтры. Если FILTER_PATTERNS пустой, INPUT_FILTER
# применяется ко всем файлам.
FILTER_PATTERNS =
# 78. Если FILTER_SOURCE_FILES тег установлен в YES, то входной фильтр (если установлен
# INPUT_FILTER) будет использоваться для фильтрации входных файлов когда вырабатывается список
# обозреваемых файлов (т.е. когда SOURCE_BROWSER установлен в YES).
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# Опции конфигурации относящиеся к обзору исходников
#---------------------------------------------------------------------------
# 79. Если тег SOURCE_BROWSER установлен в YES тогда будет генерироваться список исходных файлов.
# Документируемые сущности будут связаны перекрестными ссылками со своими исходными файлами.
# Примечание: Для удаления всех исходных файлов из генерируемой документации, необходимо также
# тег VERBATIM_HEADERS установить NO. Если в конфиге включены CALL_GRAPH или CALLER_GRAPH
# тогда эту опцию также необходимо включить. Если этого не сделать, то doxygen будет выдывать
# предупреждения и включит её в любом случае.
SOURCE_BROWSER = NO
# 80. Установив тег INLINE_SOURCES в YES позволит включать тело
# функций и классов в документацию напрямую.
INLINE_SOURCES = NO
# 81. Установка тега STRIP_CODE_COMMENTS в YES (по умолчанию) будет говорить
# doxygen о сокрытии любых специальных блочных комментариев из фрагмментов генерируемого исходного кода.
# Обычные C и C++ комментарии будут всегда оставаться видимыми.
STRIP_CODE_COMMENTS = YES
# 82. Если тег REFERENCED_BY_RELATION установлен в YES (по умолчанию)
# тогда для каждой документируемой функции будут сделаны
# ссылки на другие связанные документированные функции.
REFERENCED_BY_RELATION = YES
# 83. Если тег REFERENCES_RELATION установлен в YES (по умолчанию)
# то для каждой документируемой функции будут сделаны
# ссылки на все вызывающие/используемые документируемые сущности.
REFERENCES_RELATION = YES
# 84. Если тег REFERENCES_LINK_SOURCE установлен в YES (по умолчанию)
# и тег SOURCE_BROWSER установлен в YES, то ссылки из функций
# в списках REFERENCES_RELATION и REFERENCED_BY_RELATION будут
# связаны с исходным кодом. Иначе они будут связаны с документацией.
REFERENCES_LINK_SOURCE = YES
# 85. Если тег USE_HTAGS установлен в YES то ссылки на исходный код
# будут точкой в генерируемом HTML htags(1) программе вместо doxygen
# встроенного обозревателя исходников. htags программа является частью GNU's глобальной системы
# тегов исходных кодов (see http://www.gnu.org/software/global/global.html). Вам необходима
# версия 4.8.6 или выше.
USE_HTAGS = NO
# 86. Если тег VERBATIM_HEADERS установлен в YES (по умолчанию) то Doxygen
# будет генерировать дословную копию заголовочного файла для каждого класса для
# которого указана инструкция include. Для отключения такого поведения необходимо использовать значение NO.
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# Опции конфигурации связанные с алфавитным указателем
#---------------------------------------------------------------------------
# 87. Если тег ALPHABETICAL_INDEX установлен в YES, будет создан алфавитный указатель
# описания всех генерируемых сущностей. Рекомендуется включить этот тег
# если проект содержит множество классов, структур, объединений или интерфейсов.
ALPHABETICAL_INDEX = NO
# 88. Если включена опция алфавитного указателя (тег ALPHABETICAL_INDEX) то
# тег COLS_IN_ALPHA_INDEX используется для указания количества колонок
# на которые будет разбит список (это может быть цифра в диапазоне [1..20])
COLS_IN_ALPHA_INDEX = 5
# 89. В случае если все классы в проекте начинаются с общего префикса, все
# классы будут помещены под некоторый заголовок в алфавитном указателе.
# Тег IGNORE_PREFIX используется для указания одного или нескольких префиксов которые
# будут игнорированы при генерации индексных заголовков.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Конфигурационные опции связанные с выводом документации в формате HTML
#---------------------------------------------------------------------------
# 90. Если тег GENERATE_HTML установлен в YES (по умолчанию) Doxygen будет
# генерировать документацию в формате HTML.
GENERATE_HTML = YES
# 91. Тег HTML_OUTPUT указывает где будет располагаться генерируемая в формате HTML документация.
# Если в значении тега OUTPUT_DIRECTORY указан относительный путь, то он будет
# являться префиксом каталога для HTML документации. Если значение тего пустое, то будет использовано значение `html'.
HTML_OUTPUT = html
# 92. Тег HTML_FILE_EXTENSION используется для указания расширения файла
# каждой генерируемой HTML страницы (например: .htm,.php,.asp). Если значение пустое
# то doxygen будет генерировать файлы с расширением .html.
HTML_FILE_EXTENSION = .html
# 93. Тег HTML_HEADER используется для указания персонального HTML верхний колонтитул
# для каждой генерируемой HTML страницы. Если значение пустое, то doxygen будет генерировать стандартный верхний колонтитул.
HTML_HEADER =
# 94. Тег HTML_FOOTER используется для указания персонального текста HTML нижней части
# каждой генерируемой HTML страницы. Если значение пустое, то doxygen будет генерировать
# стандартный нижний колонтитул.
HTML_FOOTER =
# 95. Тег HTML_STYLESHEET используется для указания определенной пользователем каскадной
# таблицы стилей которая используется для каждой HTML страницы. Это может использоваться для
# точной настройки отображения HTML страниц. Если значение тега пусто, doxygen
# будет генерировать лист стиля по умолчанию. Примечательно что doxygen будет пробовать копировать
# файл таблицы стилей в каталог вывода HTML, поэтому не помещайте свой собственный
# лист стилей в каталог вывода HTML, иначе он бедет перезаписан!
HTML_STYLESHEET =
# 96. Если HTML_ALIGN_MEMBERS тег установлен в YES, то члены классов,
# файлов или пространств имён будут выравнены в HTML с использованием таблиц. Если тег установить в
# NO то будет использован список с точками.
HTML_ALIGN_MEMBERS = YES
# 97. Если тег GENERATE_HTMLHELP установлен в YES, то будут сгенерированы дополнительные указательные файлы
# которые могут быть использованы как набор входных файлов для инструментов
# наподобие Microsoft HTML help workshop которые создают сжатые HTML файлы-справочники (.chm)
# из генерируемой HTML документации.
GENERATE_HTMLHELP = NO
# 98. Если тег HTML_DYNAMIC_SECTIONS установлен в YES то генерируемая HTML
# документация будет содержать секции которые могут скрываться и отображаться
# после загрузки страницы. Для такого поведения от браузера требуется поддерживать
# JavaScript и DHTML(например Mozilla 1.0+, Firefox
# Netscape 6.0+, Internet explorer 5.0+, Konqueror, или Safari).
HTML_DYNAMIC_SECTIONS = NO
# 99. Если тег GENERATE_HTMLHELP установлен в YES, то тег CHM_FILE может
# быть использован для указания имени результирующего .chm файла. Вы
# можете добавить путь перед именем файла если результат
# должен быть записан в каталог отличный от каталога вывода HTML.
CHM_FILE =
# 100. Если тег GENERATE_HTMLHELP установлен в YES, то HHC_LOCATION используется
# для указания расположения (абсолютный путь включая имя файла)
# программы HTML help compiler (hhc.exe). Если значение не пустое, то doxygen будет пробовать запустить
# программу HTML help compiler на генерацию index.hhp.
HHC_LOCATION =
# 101. Если тег GENERATE_HTMLHELP установлен в YES, то тег GENERATE_CHI является
# управляющим флагом, который определяет будет ли создан отдельный индексный файл (.chi) при значении (YES) или
# его содержимое будет включено в основной .chm файл, при значении (NO).
GENERATE_CHI = NO
# 102. Если тег GENERATE_HTMLHELP установлен в YES, то тег BINARY_TOC является флагом
# который определяет будет ли создана двоичная таблица содержимого (YES) или
# нормальная таблица содержимого (NO) в .chm файле.
BINARY_TOC = NO
# 103. Тег TOC_EXPAND является флагом который может быть установлен в YES для добавления дополнительных элементов описывающих
# групповые члены в содержимое HTML help документации и в отображаемое дерево документации.
TOC_EXPAND = NO
# 104. Тег DISABLE_INDEX используется для включения/выключения сборного индекса-указателя
# в верху каждой HTML страницы. Значение NO (по умолчанию) включает указатель в документацию и
# значение YES исключает его из документации.
DISABLE_INDEX = NO
# 105. Этот тег используется для установки количества, являющегося одним из элементов перечисления (диапазон [1..20]),
# групп в одной строке генерируемой HTML документации.
ENUM_VALUES_PER_LINE = 4
# 106. Если тег GENERATE_TREEVIEW установлен в YES, то панель ссылок с края
# на генерируемое содержимое будет в деревоподобной индексной структуре (подобно той которая
# создаётся для HTML Help). Для этого браузер должен поддерживать
# JavaScript, DHTML, CSS и фреймы (например Mozilla 1.0+,
# Netscape 6.0+, Internet explorer 5.0+, или Konqueror). Пользователям Windows
# вероятно лучше выключить HTML help свойства.
GENERATE_TREEVIEW = NO
# 107. Если иерархическая структура документации доступна (тег GENERATE_TREEVIEW) тогда этот тег
# используется для установки начальной ширины (в пикселях) фрейма в котором дерево
# отображается.
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# Опции конфигурации связанные с выводом в формате LaTeX
#---------------------------------------------------------------------------
# 108. Если тег GENERATE_LATEX установлен в YES (по умолчанию) Doxygen будет
# генерировать документацию в формате Latex.
GENERATE_LATEX = YES
# 109. LATEX_OUTPUT тег используется для указания, где документация в формате LaTeX будет располагаться.
# Если указан относительный путь то значение OUTPUT_DIRECTORY будет
# являться началом пути. Если значение пустое, то будет использовано значение `latex'.
LATEX_OUTPUT = latex
# 110. Тег LATEX_CMD_NAME используется для указания имени команды вызова LaTeX.
# Если значение пустое, то `latex' будет использовано как имя команды по умолчанию.
LATEX_CMD_NAME = latex
# 111. Тег MAKEINDEX_CMD_NAME используется для указания имени команды
# генерирующей индекс для LaTeX. Если значение пустое, то `makeindex' будет использовано как
# имя команды по умолчанию.
MAKEINDEX_CMD_NAME = makeindex
# 112. Если тег COMPACT_LATEX установлен в YES, то Doxygen генерирует более
# компактную LaTeX документацию. Это может быть полезным для маленьких проектов и может помочь
# сохранить несколько деревьев (иерархий) в одном.
COMPACT_LATEX = NO
# 113. Тег PAPER_TYPE устанавливает тип бумаги которая используется
# при печати. Возможные значения: a4, a4wide, letter, legal и
# executive. При пустом значении будет использовано a4wide.
PAPER_TYPE = a4wide
# 114. Тег EXTRA_PACKAGES определяет одно или несколько имен пакетов LaTeX
# которые будут включены в вывод LaTeX.
EXTRA_PACKAGES =
# 115. Тег LATEX_HEADER используется для указания частных LaTeX заголовков для
# генерируемой документации latex. Заголовок должен содержать всё до
# первой главы. Если значение пустое, то doxygen будет генерировать
# стандартный заголовок. Примечание: используйте этот тег только если вы знаете что делаете!
LATEX_HEADER =
# 116. Если PDF_HYPERLINKS тег установлен в YES, то LaTeX при генерации
# будет подготавливаться для преобразования в pdf (используя ps2pdf). Формат файла pdf будет
# содержать ссылки (подобные HTML документации) вместо ссылок на страницы.
# Это сделает документацию подходящей для интерактивного просмотра, используя pdf обозреватель.
PDF_HYPERLINKS = NO
# 117. Если тег USE_PDFLATEX установлен в YES, pdflatex будет использоваться вместо
# простого latex в генерируемом Makefile. Установка этой опции в YES позволит
# повысить качество PDF документации.
USE_PDFLATEX = NO
# 118. Если тег LATEX_BATCHMODE установлен в YES, то doxygen будет добавлять команду \\batchmode.
# в генерируемые LaTeX файлы. Это будет говорить LaTeX о необходимости
# запускаться в случае возникновения ошибки, вместо того чтобы спрашивать у пользователя помощи.
# Эта формула также используется для генерации формал в HTML.
LATEX_BATCHMODE = NO
# 119. Если тег LATEX_HIDE_INDICES установлен в YES то doxygen не будет
# включать указатель глав (подобный файловому указателю, смешанному указателю, и т.д.)
# в вывод.
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# Конфигурационные опции связанные с выводом в формате RTF
#---------------------------------------------------------------------------
# 120. Если тег GENERATE_RTF установлен в YES, то Doxygen будет генерировать документацию в формате RTF.
# RTF оптимизирован для Word 97 и может не быть весьма прекрасным при использовании
# других программ для чтения RTF или его редактирования.
GENERATE_RTF = NO
# 121. Тег RTF_OUTPUT используется для указания того, где RTF документация будет расположена.
# Если в значении указан относительный путь, то OUTPUT_DIRECTORY будет
# являться началом этого пути. При пустом значении, будет использовано `rtf' как путь по умолчанию.
RTF_OUTPUT = rtf
# 122. Если тег COMPACT_RTF установлен в YES, то Doxygen сгенерирует более компактную
# RTF документацию. Это может быть полезно для маленьких проектов и может помочь в
# сохранении нескольких деревьев в одном.
COMPACT_RTF = NO
# 123. Если тег RTF_HYPERLINKS установлен в YES, то документация RTF
# будет содержать hyperlink поля. RTF файл будет содержать
# ссылки (подобные ссылкам в HTML документации) вместо ссылок на страницы.
# Это делает выходную документацию удобной для интерактивного просмотра используя WORD или другую
# программу которая поддерживает такие ссылки.
# Примечание: wordpad (write) и многие другие программы не поддерживают такие ссылки.
RTF_HYPERLINKS = NO
# 124. Загружает таблицу стилей из файла. Синтаксис подобен doxygen
# файлу конфигурации, т.е. последовательное связывание. Вам необходимо только обеспечить
# замены, ожидаемые объявления и установить значения по умолчанию.
RTF_STYLESHEET_FILE =
# 125. Устанавливает опциональные переменные используемые в генерируемом rtf документе.
# Синтаксис подобен конфигурационному файлу doxygen.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# Опции конфигурации связанные с выводом документации в формате страниц man
#---------------------------------------------------------------------------
# 126. Если тег GENERATE_MAN установлен в YES (по умолчанию), то Doxygen будет
# генерировать документацию в формате страниц man.
GENERATE_MAN = NO
# 127. Тег MAN_OUTPUT используется для указания местоположения документации генерируемой в формате страниц man.
# Если значение является относительным путем, то OUTPUT_DIRECTORY будет
# будет началом этого пути. Если значение пустое, то `man' будет использовано как путь по умолчанию.
MAN_OUTPUT = man
# 128. Тег MAN_EXTENSION определяет расширение, которое будет добавлено к
# генерируемой документации в формате страниц man (по умолчанию это секция подпрограмм .3)
MAN_EXTENSION = .3
# 129. Если тег MAN_LINKS установлен в YES и Doxygen генерирует документацию в формате страниц man,
# то будет сгенерирован один дополнительный man файл для каждой сущности
# документируемой в страницах man. Эти дополнительные файлы
# являются просто исходниками настоящих страниц man, но без man команд
# что делает невозможным поиск корректной страницы. По умолчанию используется NO.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Опции конфигурации связанные с выводом в XML output
#---------------------------------------------------------------------------
# 130. Если тег GENERATE_XML установлен в YES, то Doxygen будет
# генерировать XML файл который содержит структуру
# кода и всю документацию.
GENERATE_XML = NO
# 131. Тег XML_OUTPUT используется для указания того, где будет размещаться XML документация.
# Если указывается относительный путь, то OUTPUT_DIRECTORY будет
# располагаться в начале пути. При пустом значении строка `xml' будет использоваться как путь по умолчанию.
XML_OUTPUT = xml
# 132. Тег XML_SCHEMA используется для указания XML схемы,
# которая может быть использована XML анализатором при проверке
# синтаксиса XML файлов на правильность формирования.
XML_SCHEMA =
# 133. Тег XML_DTD используется для указания месторасположения файла XML DTD (файла уточнения синтаксиса документа),
# который может быть использован при работе XML анализатора для
# проверки синтаксиса XML файлов.
XML_DTD =
# 134. Если тег XML_PROGRAMLISTING установлен в YES, то Doxygen будет
# сваливать программные листинги (включая подсвечивание синтаксиса
# информацию о перекрестных ссылках) в формате XML. Примечательно что
# включение этой опции будет значительно увеличивать размер вывода в формате XML.
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# Опции конфигурации для формате AutoGen Definitions
#---------------------------------------------------------------------------
# 135. Если тег GENERATE_AUTOGEN_DEF установлен в YES, то Doxygen будет
# генерировать файл AutoGen Definitions (смотри autogen.sf.net)
# который содержит структуру кода, включая всю
# документацию. Примечательно что это свойство всё ещё экспериментальное
# и неполностью готово в данный момент.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Опции конфигурации связанные с выводом в формате Perl module
#---------------------------------------------------------------------------
# 136. Если тег GENERATE_PERLMOD установлен в YES, то Doxygen будет
# генерировать файл в формате Perl module который содержит структуру
# кода, включая всю документацию. Примечательно что это свойство
# всё ещё экспериментальное и не полностью реализовано
# в данный момент.
GENERATE_PERLMOD = NO
# 137. Если тег PERLMOD_LATEX установлен в YES, то Doxygen будет генерировать
# необходимые правила Makefile, Perl скрипты и код LaTeX code позволяющие
# генерировать PDF и DVI форматы из формата Perl module.
PERLMOD_LATEX = NO
# 138. Если тег PERLMOD_PRETTY установлен в YES, то формат Perl module будет
# прекрасно отформатирован для анализа человеком в текстовом редакторе. Это полезно
# если вы хотите понять, как формируется документация. В другом случае, если этот
# тег установлен в NO, то размер документации формата Perl module будет очень мал
# и будет анализироваться Perl-ом.
PERLMOD_PRETTY = YES
# 139. Имена даваемые переменным в генерируемом doxyrules.make файле
# будут предваряться строкой содержащейся в PERLMOD_MAKEVAR_PREFIX.
# Это полезно для возможности различения doxyrules.make файлов подключаемых в один
# Makefile чтобы одноименные переменные не переопределялись.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Опции конфигурации связанные с препроцессором
#---------------------------------------------------------------------------
# 140. Если тег ENABLE_PREPROCESSING установлен в YES (по умолчанию), то Doxygen будет
# оценивать все C-препроцессорные директивы найденные в исходниках и включаемых
# файлах.
ENABLE_PREPROCESSING = YES
# 141. Если тег MACRO_EXPANSION установлен в YES, то Doxygen будет расширять все
# макроимена в исходном коде. Если значение NO (по умолчанию) то будет выполнена только условная компиляция.
# Макрораширение может быть выполнено управляемым
# способом, путем установки EXPAND_ONLY_PREDEF в YES.
MACRO_EXPANSION = NO
# 142. Если тег EXPAND_ONLY_PREDEF и тег MACRO_EXPANSION оба установлены в YES
# то макрорасширение ограничивается в макрос определенный
# PREDEFINED и EXPAND_AS_DEFINED тегами.
EXPAND_ONLY_PREDEF = NO
# 143. Если тег SEARCH_INCLUDES установлен в YES (по умолчанию) то подключаемые файлы
# будут искаться в пути определенном INCLUDE_PATH (смотри ниже) в случае если будет всречена директива #include.
SEARCH_INCLUDES = YES
# 144. Тег INCLUDE_PATH указывает один или несколько каталогов, которые
# содержат включаемые файлы которые не являются входными файлами но должны быть обработаны
# препроцессором.
INCLUDE_PATH =
# 145. Можно использовать тег INCLUDE_FILE_PATTERNS для указания одного или нескольких шаблонов
# (типа *.h и *.hpp) для фильтрации выходных каталогов для заголовочных файлов.
# Если значение пустое, то будут использованы шаблоны указанные в FILE_PATTERNS.
INCLUDE_FILE_PATTERNS =
# 146. Тег PREDEFINED используется для указания одного или нескольких макро имён которые
# которые объявляются перед запуском препроцессора (подобно -D опции компилятора
# gcc). Аргументом тега является список макросов в виде: имя
# или имя=объявление (без пробелов). В случае если объявление не указано,
# то предполагается что оно равно 1. Для предотвращения макрообъявления в начале
# делается отмена объявление через #undef или рекурсивное расширение используя := operator
# вместо = operator.
PREDEFINED =
# 147. Если тег MACRO_EXPANSION и тег EXPAND_ONLY_PREDEF установлены в YES тогда
# этот тег может использоваться для указания списка макро имён которые должны быть расширены.
# Будут использованы макрообъявления которые будут найдены в исходниках.
# используйте тег PREDEFINED если хотите использовать различные макрообъявления.
EXPAND_AS_DEFINED =
# 148. Если тег SKIP_FUNCTION_MACROS установлен в YES (по умолчанию) то
# препроцессор doxygen's будет удалять все функция-подобные макросы одиноко расположенные в строке
# имеющие все все буквы в верхнем регистре, и не заканчивающеся точкой с запятой. Такие
# функциональные макросы обычно используются для boiler-plate кода, и будет путать
# анализатор, если не будет удалён.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Конфигурация::дополнения связанные с внешними ссылками
#---------------------------------------------------------------------------
# 149. TAGFILES опция используется для указания одного или нескольких tagfiles.
# Выборочно начальное расположение внешней документации
# может быть указано для каждого tagfile. Формат tag file без
# этого расположения следующий:
# TAGFILES = file1 file2 ...
# Добавление расположения для tag files выполняется следующим образом:
# TAGFILES = file1=loc1 "file2 = loc2" ...
# где "loc1" и "loc2" могут быть как абсолютные так и относительные пути или
# URL-ы. Если расположение представлено для каждого тега, инструмент installdox
# не может быть запущен по корректным ссылкам.
# Примечательно что каждый tag file должен иметь уникальное имя
# (где имя НЕ включается в путь)
# Если tag file не обнаружен в каталоге в котором запущен doxygen
# то необходимо также полностью указать в нему путь tagfile.
TAGFILES =
# 150. Когда файловое имя указано после GENERATE_TAGFILE, doxygen будет создавать
# tag file который основывается на читаемых входных файлах.
GENERATE_TAGFILE =
# 151.Если тег ALLEXTERNALS установлен в YES, то все внешние классы будут помещены
# в указатель классов. Если значение NO, то только наследуемые внешние классы
# попадут в классовый указатель.
ALLEXTERNALS = NO
# 152. Если тег EXTERNAL_GROUPS установлен в YES, то все внешние группы будут помещены
# указатель по модулям. Если значение NO, то только текущая проектная группа будет помещена
# в указатель.
EXTERNAL_GROUPS = YES
# 153. Тег PERL_PATH должен содержать абсолютный путь и имя
# интерпретатора Perl (т.е. результат выполнения в системе команды `which perl').
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Опции конфигурации связанные с инструментом dot
#---------------------------------------------------------------------------
# 154. Если тег CLASS_DIAGRAMS установлен в YES (по умолчанию), то Doxygen будет
# генерировать диаграммы наследования (в HTML, RTF и LaTeX) для классов с основой
# (супер классов). Установка тега в NO выключает формирование диаграмм. Примечательно что
# эта опция заменяется HAVE_DOT опцией описанной ниже. Эта опция используется
# для перехода на аварийный режим. Рекомендуется установить эту опцию и использовать dot, для получения
# более результативного мощного графа.
CLASS_DIAGRAMS = YES
# 155. Можно объявить сообщение последовательностью схем без doxygen комментариев используя команду \msc
# Doxygen тогда будет запускать программу mscgen (смотри http://www.mcternan.me.uk/mscgen/) для
# для генерации схем и вставки их в документацию. MSCGEN_PATH тег позволяет
# указать каталог где размещается mscgen. Если оставить этот тег пустым то программа
# будет искаться в каталогах доступных для просмотра по умолчанию.
MSCGEN_PATH =
# 156. Если тег установлен в YES, то наследуемые и связанные графы будут скрыты
# наследственностью и будут использоваться связи если цель недокументируема
# или если нет классов.
HIDE_UNDOC_RELATIONS = YES
# 157. Если вы установите тег HAVE_DOT в YES то doxygen будет связан с инструментом dot который
# расположен по стандартному пути. Этот инструмент является частью Graphviz, графического визуализатора
# от компании AT&T и Lucent Bell Labs. Другие опции в этой секции не имеют эффекта
# если эта опция установлена в NO (по умолчанию)
HAVE_DOT = NO
# 158. Если теги CLASS_GRAPH и HAVE_DOT установлены в YES то doxygen
# будет генерировать граф для каждого документируемого класса, отображая прямые и
# непрямые наследуемые связи. Установка этого тега в YES будет переустанавливать
# тег CLASS_DIAGRAMS в NO.
CLASS_GRAPH = YES
# 159. Если тег COLLABORATION_GRAPH и тег HAVE_DOT установлены в YES то doxygen
# будет генрировать граф для каждого документируемого класса отображая прямые и непрямые
# зависимости в реализации (наследуемые, локализованные, и
# переменные ссылочных классов) этого класса с другими документируемыми классами.
COLLABORATION_GRAPH = YES
# 160. Если тег GROUP_GRAPHS и тег HAVE_DOT установлены в YES то doxygen
# будет генерировать граф для групп, отображая прямые зависимости групп
GROUP_GRAPHS = YES
# 161. Если тег UML_LOOK установлен в YES, то doxygen будет генерировать наследственные и
# взаимосвязанные диаграммы в тиле подобном Унифицированному Языку моделирования OMG's Unified Modeling
# Language.
UML_LOOK = NO
# 162. Если тег установлен в YES, наследственные и взаимодейственные графы будут показывать
# связи между шаблонами и их реализациями (примерами использования).
TEMPLATE_RELATIONS = NO
# 163. Если теги ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, HAVE_DOT
# установлены в YES то doxygen будет генерировать граф для каждого документируемого файла
# показывания прямые и непрямые включения зависимостей файла
# с другими документируемыми файлами.
INCLUDE_GRAPH = YES
# 164. Если ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, и
# HAVE_DOT теги установлены в YES то doxygen будет генерировать граф для каждого
# документируемого заголовочного файла показывания документируемые файлы, которые
# прямо или косвенно включают этот файл.
INCLUDED_BY_GRAPH = YES
# 165. Если теги CALL_GRAPH, SOURCE_BROWSER, HAVE_DOT установлены в YES то doxygen будет
# генерировать граф зависимости вызовов для каждой глобальной функции или метода класса.
# Заметьте что включение этой опции будет значительно увеличивать время генерации документации.
# Так в большинстве случаев было бы лучше включить построение графа вызовов для выбранных
# функций только используя команду \callgraph.
CALL_GRAPH = NO
# 166. Если теги CALLER_GRAPH, SOURCE_BROWSER и HAVE_DOT установлены в YES то doxygen будет
# генерировать граф зависимости вызывателей для каждой глобальной функции или метода класса.
# Заметьте что включение этой опции будет значительно увеличивать время генерации документации.
# Так в большинстве случаев было бы лучше включить простоение графа вызывателей функции или метода для выбранных
# функций используя команду \callergraph.
CALLER_GRAPH = NO
# 167. Если тег GRAPHICAL_HIERARCHY и HAVE_DOT установлены в YES то doxygen
# будет рисовать графическую иерархию всех классов вместо текстового описания.
GRAPHICAL_HIERARCHY = YES
# 168. Если теги DIRECTORY_GRAPH, SHOW_DIRECTORIES и HAVE_DOT установлены в YES
# то doxygen будет показывать зависимости каталога от других каталогов
# в графическом виде. Зависимости связей определяются по директивам #include
# связывающим файлы в разных каталогах между собой.
DIRECTORY_GRAPH = YES
# 169. Тег DOT_IMAGE_FORMAT используется для установки формата изображений
# генерируемых по точке. Возможные значения png, jpg, или gif
# В случае пустого значения будет использован формат png.
DOT_IMAGE_FORMAT = png
# 170. Тег DOT_PATH используется для указания пути где инструмент dot может быть
# найден. При пустом значении, инструмент будет искаться в стандартных каталогах.
DOT_PATH =
# 171. Тег DOTFILE_DIRS используется для указания одного или нескольких каталогов которые
# содержат dot файлы, которые включаются в документацию (смотри команду
# \dotfile).
DOTFILE_DIRS =
# 172. Тег DOT_GRAPH_MAX_NODES используется для установки максимального количества узлов
# которые могут быть показаны в графе. Если количество узлов в графе становится больше чем
# это значение, то doxygen будет урезать граф, который
# визуально представляет узел как красную коробку. Заметьте что doxygen если номер
# прямого потомка корневого узла в графе уже больше чем
# MAX_DOT_GRAPH_NOTES то граф не будет отображать его вовсе. Также заметьте
# что размер графа может быть дополнительно ограничен MAX_DOT_GRAPH_DEPTH.
DOT_GRAPH_MAX_NODES = 50
# 173. Тег MAX_DOT_GRAPH_DEPTH используется для установки максимальной глубины
# графа генерируемого по точке. Значение глубины равно 3, указывает что показываться будут только узлы доступные
# из корневого не далее чем на 3 узла. Узлы
# более удалены от корневого узла будут скрыты. Замемтьте что эта настройка
# установленная в 1 или 2 может значительно уменьшить время вычисления необходимое для большого
# количества кода. Также заметьте что размер графа может быть в дальнейшем ограничен
# DOT_GRAPH_MAX_NODES. Используя значение глубины 0 для отключения ограничения.
MAX_DOT_GRAPH_DEPTH = 0
# 174. Установка тега DOT_TRANSPARENT в YES генерирует изображения с прозрачным
# фоном. По умолчанию это выключено, и картинки получаются с белым фоном.
# Предупреждение: Существует зависимость от используемой платформы, включение этой опции может привести к
# ухудшению антисглаживания меток на выступах графов (т.е. они становятся неудобными для восприятия)
DOT_TRANSPARENT = NO
# 175. Установка тега DOT_MULTI_TARGETS в YES позволяет инструменту dot генерировать множество
# файлов в одном запуске (т.е. множество, это -o и -T опции в командной строке). Это
# делает запуск dot более быстрым, но только начиная с версии (>1.8.10),
# по умолчанию это свойство отключено.
DOT_MULTI_TARGETS = NO
# 176. Если тег GENERATE_LEGEND установлен в YES (по умолчанию), то Doxygen будет
# генерировать страницу легенд с объяснением значений различных коробок и
# стрелок в графах сгенерированных инструментом dot.
GENERATE_LEGEND = YES
# 177. Если тег DOT_CLEANUP установлен в YES (по умолчанию), то Doxygen будет
# незамедлительно удалять dot файлы котрые использовались для генерации
# различных графов.
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Конфигурация::дополнения связанные с поисковым движком
#---------------------------------------------------------------------------
# 178. Тег SEARCHENGINE определяет будет или нет использован поисковый движок.
# Если его установить в NO то значения всех тегов которые ниже этого будут проигнорированы.
SEARCHENGINE = NO
[править] Комментирование исходного текста
Практически любой элемент программы (класс, функция, переменная) может быть задокументирован в системе Doxygen.
Документирование выполняется на основе двух видов комментариев:
- краткий (brief)
- и полный (detailed).
Краткие комментарии обычно описывают предназначение комментируемого элемента, а полные содержат информацию по его использованию и функционированию и чаще всего являются многострочными.
К каждому элементу программы не может быть привязано более одного краткого и полного комментария.
Для документирования какого-либо элемента программы, соответствующий комментарий располагают перед этим элементом в тексте программы. Например:
//! Оценка вектора состояния СС за дисперсией квадратурных компонент int x_stdn2_est;
Существует множество вариантов оформления комментариев:
- Возможно использовать комментарии в стиле системы JavaDoc, применяемой при документировании исходных текстов на языке Java:
/** * Оценка вектора состояния СС за дисперсией квадратурных компонент */ int x_stdn2_est;
или так
/*! * Оценка вектора состояния СС за дисперсией квадратурных компонент */ int x_stdn2_est;
как и для предыдущего случая, знаки "*" не обязательны для промежуточных строк:
/*! Оценка вектора состояния СС за дисперсией квадратурных компонент */ int x_stdn2_est;
- Еще один вариант - использование дополнительных знаков "/" или "!" в каждой строке (QT-Style):
/// /// Оценка вектора состояния СС за дисперсией квадратурных компонент /// int x_stdn2_est;
или //! //! Оценка вектора состояния СС за дисперсией квадратурных компонент //! int x_stdn2_est;
По умолчанию любой многострочный комментарий является подробным. Для объявления кратких комментариев можно так же использовать несколько методов:
* Использование команды \brief в блоке комментария:
/*! \brief краткий комментарий. * краткий комментарий. * * после пустой строки начинается подробный комментарий. */ int x_stdn2_est; 2.Для однострочных комментариев:
/// краткое описание. /** Полное описание. */ int x_stdn2_est;
или
//! краткое описание. //! многострочное //! подробное описание. int x_stdn2_est;
Иногда желательно расположить комментарий после, либо на одной строке с описываемым элементом. Для такого случая так же существуют несколько возможных способов:
1. int x_stdn2_est;; /*!< Подробный комментарий */ 2. int x_stdn2_est;; /**< Подробный комментарий */ 3. int x_stdn2_est;; //!< Подробный комментарий 4. //!< 5. int x_stdn2_est;; ///< Подробный комментарий ///< 6. int x_stdn2_est;; //!< Краткий комментарий 7. int x_stdn2_est;; ///< Краткий комментарий
Обычно предполагается, что документирующие комментарии находятся рядом с документируемым элементом. Однако, Doxygen позволяет поместить комментарий практически в любой части файла, связав его с каким-либо элементом. В этом случае необходимо указывать в блоке комментария ряд специальных команд.
Например так будет выглядеть описание класса Test, размещенное в любом месте файла:
/*! \class Test \brief Тестовый класс. Полное описание класса. */
Кроме команды \class, можно использовать множество других:
\struct - документирует структуру \union - документирует объединение \enum - документирует перечисление \fn - документирует функцию \var - документирует переменную \def - документирует макрос подстановки #define \file - документирует файл \namespace - документирует пространство имен. \typedef - документирование объявления типа \interface - документирование IDL интерфейса \package - документирование пакета на языке Java
[править] Востребованные команды
[править] Комментирование структур, переменных и т.д.
Переменные часто удобно объединять в группы:
quint32 R2; ///< Первичный акк. \f$ I^2 + Q^2 \f$
quint64 R4; ///< Первичный акк. \f$ (I^2 + Q^2)^2 \f$
quint32 R2_acum; ///< Вторичный аккумулятор R2
quint64 R4_acum; ///< Вторичный аккумулятор R4
quint32 R2_acum_copy; ///< Триггер R2_acum
quint64 R4_acum_copy; ///< Триггер R4_acum
//@}
[править] Комментирование функции
Позволяет установить оценку дисперсии (мощности шумовой составляющей) корреляционных сумм и
зафиксировать её.
@param PoMe - указатель на структуру данных блока оценки с/ш
@param stdn2_IQ - устанавливаемое значение оценки дисперсии квадратур
@return 0, если прошло успешно, 1, если предлагаемое число после сдвига не влазиет в 32 разряда
*/
int SetVariancePowerMeasure(PowerMeasure_struct *PoMe, quint32 stdn2_IQ ){
if (__CLZ(stdn2_IQ) >= x_stdn2_shift){ // Если предлагаемое число можно сдвинуть, не переполнив 32 разряда
PoMe->x_stdn2_est = stdn2_IQ;
// В случае увеличения порядка фильтра добавить сюда PoMe->x_stdn2_extr = stdn2_IQ;
PoMe->x_stdn2_est_shifted = stdn2_IQ<<x_stdn2_shift;
return 0;
}else return 1;
}
[править] Вставка TeX-формул
Для вставки TeX-формулы используются команды \f$ ... \f$
и \f[ ... \f]
, которые обрамляют TeX-разметку:
Выражение в тексте:
Выражение по центру, с новой строки:
\f[
u_{d,k} = - atan{frac{Q_k}{I_k}},
\f]
его характеристики хорошо изучены, работа наглядна.
*/
Для расширенного синтаксиса нужно дополнить опцию в Doxyfile'e:
[править] Bug, ToDo, Warning, Note
Одноименные команды вставляют одноименные заметки. Далее doxygen формирует отдельные списки, по которым можно быстро найти интересующее место в коде.
@warning Не трогать значение этой переменной
@todo Переписать функцию под новую структуру данных
@bug Ошибочно работает при x<0
@note Подробнее изложено в рабочем журнале
*/
[править] Пример из жизни
Пример документирования файлов PowerMeasure.c и PowerMeasure.h. Результат можно подглядеть тут.
#if (RECEIVER_TYPE == RECEIVER_ALPACA)
#include <math.h>
#include "FPGA.h"
#else if (RECEIVER_TYPE == RECEIVER_NIIKP_ARM)
#include "std.h"
#include <intrinsics.h>
#endif
quint32 sqrt_PoMe(quint32 x);
quint32 NearestPower2(quint32 x); // Ближайщее большее 2^n, возвращаем n
/**
Инициализация структуры данных блока оценки с/ш, сброс счетчиков.
@param PoMe - указатель на структуру данных блока оценки с/ш
@param Init_qcno - инициализационное значение отношения с/ш, в НИИ КП не используется
*/
void InitPowerMeasure(PowerMeasure_struct * PoMe, quint32 Init_qcno)
{
PoMe->x_A2_est[0] = (1<<PoMe_NoiseU2Bit_shifted<<5);
PoMe->x_stdn2_est = (1<<PoMe_NoiseU2Bit_shifted); // Для первого порядка совпадает с экстраполяцией
PoMe->x_stdn2_est_shifted = PoMe->x_stdn2_est << x_stdn2_shift;
PoMe->allow_stnd2_est = 1; // Разрешить оценивать и фильтровать дисперсию квадратур
PoMe->R2 = 0;
PoMe->R4 = 0;
PoMe->acum_counter = 0; // Счетчик второго уровня накопителя корреляционных сумм
PoMe->sum_counter = 0; // Счетчик первого уровня накопителя корреляционных сумм
PoMe->fail_counter = 0; // Счетчик подряд идущих фейлов измерений
PoMe->start_counter = 0; // Счетчик тиков фильтра СКО от разрешения, доходит до (obr_Kf_stdn_0+задержка) и застывает
PoMe->acum_threshold_lock = 0;
#if (RECEIVER_TYPE == RECEIVER_ALPACA)
if (Init_qcno > 0)
PoMe->qcno = Init_qcno;
else
PoMe->qcno = (quint32)( PoMe->x_A2_est[0] / (2.0 * PoMe->x_stdn2_est * PoMe_Tcorr) );
PoMe->qcno_dBHz = 10.0*log10(PoMe->qcno);
PoMe->qcno_dBHz_extr = PoMe->qcno_dBHz;
#endif
}
/**
По накопленным \f$\sum I_k^2+Q_k^2\f$ и \f$\sum (I_k^2+Q_k^2)^2\f$ производим
оценки дисперсии, амплитуды и квадрата амплитуды квадратур.
Основная нить вычислений:
\f[ M = \frac{R2}{K} \f]
\f[ Diskrimi = 2M^2 - \frac{R4}{K} \f]
\f[ A^2_{izm} = M - 2 \sigma^2_{filt} \f]
\f[ \sigma^2_{izm} = \frac{M - \sqrt{Diskrimi}}{2} \f]
Измерения \f$ \sigma^2_{izm} \f$ хорошенько фильтруем, чтобы не испортить \f$ A^2_{izm} \f$
@param PoMe - указатель на структуру данных блока оценки с/ш
*/
void DoPowerMeasure(PowerMeasure_struct *PoMe)
{
quint32 M;
quint32 Diskrimi;
quint32 SQ_stdn_izm;
quint32 SQ_A_izm;
//qint32 Ud_A;
qint32 Ud_stdn;
qint64 tmp64_1, tmp64_2, tmp64_3;
quint32 tmpu32_2, Diskrimi_shift;
/* Division by acum_counter */
int clz=31-__CLZ(PoMe->Accumulators_are_ready);
if((1<<clz)==PoMe->Accumulators_are_ready)
{
tmp64_1 = PoMe->R2_acum_copy >> clz; // M
tmp64_3 = PoMe->R4_acum_copy >> clz;
}
else
{
tmp64_1 = PoMe->R2_acum_copy / PoMe->Accumulators_are_ready; // M
tmp64_3 = PoMe->R4_acum_copy / PoMe->Accumulators_are_ready;
}
/***/
PoMe->acum_threshold_lock = 0;
tmp64_2 = 2*tmp64_1*tmp64_1;
tmp64_2 = tmp64_2 - tmp64_3; // Diskrimi
if (tmp64_2 < 0)tmp64_2 = 0;
tmpu32_2 = ((tmp64_2 >> 32)&0xFFFFFFFF);
Diskrimi_shift = 32 - __CLZ(tmpu32_2);
if (Diskrimi_shift & 0x1) Diskrimi_shift++; // Чётное must be
M = (tmp64_1&0xFFFFFFFF);
Diskrimi = ((tmp64_2 >> Diskrimi_shift)&0xFFFFFFFF);
PoMe->Accumulators_are_ready = 0;
PoMe->IQ_Power = M;
/* Измерение квадрата амплитуды */
if (M > 2*PoMe->x_stdn2_est){
SQ_A_izm = M - 2*PoMe->x_stdn2_est;
PoMe->fail_counter = 0;
}
else {
PoMe->fail_counter++;
if (PoMe->x_A2_est[0] > (1<<PoMe_NoiseU2Bit_shifted) ) SQ_A_izm = (1<<PoMe_NoiseU2Bit_shifted);
else SQ_A_izm = PoMe->x_A2_est[0] - PoMe->x_A2_est[0]/2; //0.05*(0 - PoMe->x_A2_est[0]);
}
/***/
/* Фильтр амплитуды и её квадрата */
PoMe->x_A2_est[0] = SQ_A_izm;
PoMe->x_A_est = sqrt_PoMe( PoMe->x_A2_est[0] );
/***/
//#ifdef __Model
// static FILE* fid_ampout=0;
// if (!fid_ampout)
// {
// fid_ampout = fopen("amp.csv", "wt");
// fprintf(fid_ampout,"tmp64_1;tmp64_2;tmp64_3;SQ_stdn;tmp;Diskrimi;M;SQ_A_izm\n");
// }
// fprintf(fid_ampout,"%I64u;%I64u;%I64u;%d;%d;%u;%u;%u\n",
// tmp64_1,tmp64_2,tmp64_3,
// SQ_stdn_izm,
// tmp,
// Diskrimi,
// M,
// SQ_A_izm);
// fflush(fid_ampout);
//#endif
if (PoMe->allow_stnd2_est == 1){
quint32 tmp;
/* Измерение квадрата СКО квадратур */
if ( Diskrimi > 0 ) {
tmp = sqrt_PoMe(Diskrimi);
if (tmp != 0){ // Одна итерация по Герону для увеличения точности до требуемой
tmp += (int(Diskrimi) -int(tmp*tmp))/2 / int(tmp); // Обратное смещение с учетом смещения в корне
}
tmp <<= (Diskrimi_shift/2);
if (M > tmp)
SQ_stdn_izm = (M - tmp) / 2 ; //
else
SQ_stdn_izm = 0;
} else
SQ_stdn_izm = M / 2;
/***/
if (SQ_stdn_izm > 2*PoMe->x_stdn2_est) // При резком изменении амплитуды на интервале оценивания
SQ_stdn_izm = 2*PoMe->x_stdn2_est; // происходит аномальный выброс, т.к. процесс не соответствует модели постоянства параметра
/* Фильтр диспресии квадратурных компонент */
Ud_stdn = (SQ_stdn_izm<<x_stdn2_shift) - PoMe->x_stdn2_est_shifted; // Дискриминатор дисперсии квадратур
quint32 start_delay = 10; // First PoMe_obr_Kf_stdn_0 steps Kalman is used
if (PoMe->start_counter >= (PoMe_obr_Kf_stdn_0 + start_delay)) // После подстройки опять затягиваем фильтр
PoMe->x_stdn2_est_shifted += Ud_stdn / PoMe_obr_Kf_stdn_0;
else if (PoMe->start_counter < start_delay) { // На начальном этапе фильтр затянут
PoMe->start_counter++;
PoMe->x_stdn2_est_shifted += Ud_stdn / PoMe_obr_Kf_stdn_0;
}
else { // После выжидания start_delay расширяем фильтр и быстро подстраиваемся
PoMe->start_counter++;
PoMe->x_stdn2_est_shifted += Ud_stdn >> NearestPower2(PoMe->start_counter - start_delay);
}
PoMe->x_stdn2_est = PoMe->x_stdn2_est_shifted>>x_stdn2_shift;
/***/
} // if (PoMe->allow_stnd2_est == 1)
#if (RECEIVER_TYPE == RECEIVER_ALPACA)
PoMe->SQ_A_izm = SQ_A_izm;
PoMe->SQ_stdn_izm = SQ_stdn_izm;
PoMe->qcno = (quint32)( PoMe->x_A2_est[0] / (2.0 * PoMe->x_stdn2_est * PoMe_Tcorr) );
PoMe->qcno_dBHz = 10.0*log10(PoMe->qcno);
PoMe->qcno_dBHz_extr = PoMe->qcno_dBHz;
#endif
}
/**
Сопоставляет выбранному номеру порога число требуемых накоплений второго уровня.
@param PoMe - указатель на структуру данных блока оценки с/ш
@todo Что-то слишком громозко и сложно, нужно переделать систему порогов
*/
void SetAccumThreshold(PowerMeasure_struct *PoMe){
switch (PoMe->acum_threshold_level){
case 5:
PoMe->acum_threshold = PoMe_Threshold_5;
break;
case 4:
PoMe->acum_threshold = PoMe_Threshold_4;
break;
case 3:
PoMe->acum_threshold = PoMe_Threshold_3;
break;
case 2:
PoMe->acum_threshold = PoMe_Threshold_2;
break;
case 1:
PoMe->acum_threshold = PoMe_Threshold_1;
break;
default:
PoMe->acum_threshold = PoMe_Threshold_def;
}
}
/**
Производит необходимые накопления суммы квадратов корреляционных сумм,
устанавливает пороги накопления по детектируемой мощности на входе,
при достижении порога вызывает функцию обработки накоплений DoPowerMeasure.
Различаются накопления двух уровней.
- первый: накопление PoMe_sum_counter_max величин U2, результат - детектор мощности
- второй: накопление acum_threshold сумм первого уровня, затем вызов DoPowerMeasure
@param PoMe - указатель на структуру данных блока оценки с/ш
@param U2 - сумма квадратов корреляционных сумм \f$U2 = I_k^2 + Q_k^2\f$
*/
void AccumPowerMeasure(PowerMeasure_struct *PoMe, quint32 U2){
quint64 tmpu64;
quint32 tmpu32;
int overflow_F_ = 0;
PoMe->sum_counter++; if (PoMe->sum_counter == PoMe_sum_counter_max) PoMe->sum_counter = 0;
tmpu32 = PoMe->R2 + U2;
if (PoMe->R2 <= tmpu32) // overflow defence
PoMe->R2 = tmpu32; // sum I^2 + Q^2
else{ // impossible, if PoMe_sum_counter_max and U2_SHIFT are correct
PoMe->R2 = U2;
overflow_F_ = 1;
}
tmpu64 = PoMe->R4 + (quint64)(U2) * (quint64)(U2);
if ( (PoMe->R4 <= tmpu64) & (overflow_F_ == 0) ) // overflow defence
PoMe->R4 = tmpu64; // sum (I^2 + Q^2)^2
else{ // impossible, if PoMe_sum_counter_max and U2_SHIFT are correct
PoMe->R4 = (quint64)(U2) * (quint64)(U2);
}
if (PoMe->sum_counter == (PoMe_sum_counter_max - 1) )
{
quint64 tmpu64_1, tmpu64_2;
quint32 tmpu32_1, tmpu32_2;
if (overflow_F_ == 0){
tmpu64_1 = PoMe->R4 / PoMe_sum_counter_max;
tmpu32_1 = PoMe->R2 / PoMe_sum_counter_max;
} else {
tmpu64_1 = PoMe->R4;
tmpu32_1 = PoMe->R2;
}
PoMe->R2 = 0;
PoMe->R4 = 0;
tmpu64_2 = PoMe->R4_acum + tmpu64_1;
tmpu32_2 = PoMe->R2_acum + tmpu32_1;
if ( (PoMe->R4_acum <= tmpu64_2)&(PoMe->R2_acum <= tmpu32_2)&(overflow_F_ == 0) ){ // Переполнения нет
PoMe->R4_acum = tmpu64_2;
PoMe->R2_acum = tmpu32_2;
PoMe->acum_counter++;
}else if ( (tmpu64_1 > PoMe->R4_acum)||(tmpu32_1 > PoMe->R2_acum)||(overflow_F_ == 0) ){
// impossible, if PoMe_sum_counter_max, U2_SHIFT and max[threshold] are correct
overflow_F_ = 1;
PoMe->R4_acum = tmpu64_1; // А раз оно такое большое, то будем по нему и работать
PoMe->R2_acum = tmpu32_1;
PoMe->acum_counter = 1;
}else { // Штатное переполнение по капле: где-то что-то мы проворонили
overflow_F_ = 1; // Надеяться и ждать, что сейчас всё пучком пройдет)
}
// *********** Threshold setting **********************
tmpu32_2 = 32 - __CLZ(tmpu32_1); // Num of ones in E[U2]
if ( tmpu32_2 > (PoMe_NoiseU2Bit_shifted + 8) ){ // Power >> Noise Power
PoMe->acum_threshold_level = 5;
}else if ( tmpu32_2 > (PoMe_NoiseU2Bit_shifted + 4) ){
PoMe->acum_threshold_level = 4;
}else if ( tmpu32_2 > (PoMe_NoiseU2Bit_shifted+2) ){
PoMe->acum_threshold_level = 3;
}else
if ( (PoMe->x_A2_est[0])>>(PoMe_NoiseU2Bit_shifted-1)){
PoMe->acum_threshold_level = 2;
}else{
PoMe->acum_threshold_level = 1;
}
if (PoMe->acum_counter == 1) PoMe->acum_threshold_level_first = PoMe->acum_threshold_level;
if ((PoMe->acum_threshold_level - PoMe->acum_threshold_level_first) > 1){ // Up
PoMe->acum_threshold_lock = 1;
SetAccumThreshold(PoMe);
PoMe->R4_acum = tmpu64_1; // Old data so old
PoMe->R2_acum = tmpu32_1;
PoMe->acum_counter = 1;
PoMe->acum_threshold_level_first = PoMe->acum_threshold_level; // One second or more
if (PoMe->acum_threshold_level_first > 3)
PoMe->acum_threshold = 1;
else if (PoMe->acum_threshold_level_first == 3)
PoMe->acum_threshold = 2;
else
PoMe->acum_threshold = 4;
}else if ( (PoMe->acum_threshold_level_first - PoMe->acum_threshold_level) > 1){// Down
if (PoMe->acum_threshold_lock == 0){
PoMe->R4_acum = tmpu64_1; // Old data so old
PoMe->R2_acum = tmpu32_1;
PoMe->acum_counter = 1;
PoMe->acum_threshold_level_first = PoMe->acum_threshold_level;
PoMe->acum_threshold_lock = 1;
PoMe->acum_threshold = (1024 / PoMe_sum_counter_max); // One second
}
}else
if ( (PoMe->acum_threshold_lock == 0) & (PoMe->acum_counter == 1) )
SetAccumThreshold(PoMe);
PoMe->acum_threshold=8; // @bug: ВРЕМЕННО
if ( (PoMe->acum_counter >= PoMe->acum_threshold) // Превысили порог накопления для текущего qcno
|| (overflow_F_) // Overflow in R2_acum or R4_acum
){
PoMe->Accumulators_are_ready = PoMe->acum_counter; PoMe->acum_counter = 0;
PoMe->R4_acum_copy = PoMe->R4_acum; PoMe->R4_acum = 0;
PoMe->R2_acum_copy = PoMe->R2_acum; PoMe->R2_acum = 0;
}
}
}
/**
Позволяет установить оценку дисперсии (мощности шумовой составляющей) корреляционных сумм и
зафиксировать её.
@param PoMe - указатель на структуру данных блока оценки с/ш
@param stdn2_IQ - устанавливаемое значение оценки дисперсии квадратур
@return 0, если прошло успешно, 1, если предлагаемое число после сдвига не влазиет в 32 разряда
*/
int SetVariancePowerMeasure(PowerMeasure_struct *PoMe, quint32 stdn2_IQ ){
if (__CLZ(stdn2_IQ) >= x_stdn2_shift){ // Если предлагаемое число можно сдвинуть, не переполнив 32 разряда
PoMe->x_stdn2_est = stdn2_IQ;
// В случае увеличения порядка фильтра добавить сюда PoMe->x_stdn2_extr = stdn2_IQ;
PoMe->x_stdn2_est_shifted = stdn2_IQ<<x_stdn2_shift;
return 0;
}else return 1;
}
/**
Разрешает работу фильтру дисперсии квадратру, сбрасывает его счетчик.
@param PoMe - указатель на структуру данных блока оценки с/ш
*/
void AllowVariancePowerMeasure(PowerMeasure_struct *PoMe){
PoMe->allow_stnd2_est = 1;
PoMe->start_counter = 0;
}
#if (RECEIVER_TYPE == RECEIVER_ALPACA)
/**
Возвращает число подряд идущих нулевых разрядов слева в бинарном представлении 32-разрядного числа.
Например, для x=b'00000111 вернет 29.
@param x
*/
int __CLZ(int x){
int i;
for (i=31; i>=0; i--){
if (x >> i)
return (31 - i);
}
return 32;
}
#endif
#if (RECEIVER_TYPE == RECEIVER_ALPACA)
#define sh_sqrt 10
#else
static const int sh_sqrt=10; // Смещение вывода функции fix_sqrt
#endif
/**
Нормирует 1.0 <= x <=4.0 * (2** -sh_sqrt) .
@param x - нормируемое число
@param exp - указатель, через который возвращается сдвиг
@return Результат нормировки
*/
quint32 norm_x_PoMe(quint32 x, qint32 * exp){
*exp =0;
int razr=32-__CLZ(x);
// printf("razr = %d \n", razr);
if(razr<sh_sqrt){
x=x<<(sh_sqrt-razr);
*exp=-(sh_sqrt-razr);
// printf("razr < exp = %d; x = %d \n", *exp, x);
}
else if(razr > (sh_sqrt+1)){
x=x>>(razr-sh_sqrt);
*exp=razr-sh_sqrt;
// printf("razr > exp = %d; x = %d \n", *exp, x);
}
if( (*exp) & 1){
x=x<<1;
(*exp)--;
// printf("exp not even exp = %d; x = %d \n", *exp, x);
}
return x;
}
#if (RECEIVER_TYPE == RECEIVER_ALPACA)
#define K_sqrt1 (qint32)(0.09977*(1<<sh_sqrt)+0.5)
#define K_sqrt2 (qint32)(0.71035*(1<<sh_sqrt)+0.5)
#define K_sqrt3 (qint32)(0.3866*(1<<sh_sqrt)+0.5)
#else
static const qint32 K_sqrt1 = (qint32)(0.09977*(1<<sh_sqrt)+0.5);
static const qint32 K_sqrt2 = (qint32)(0.71035*(1<<sh_sqrt)+0.5);
static const qint32 K_sqrt3 = (qint32)(0.3866*(1<<sh_sqrt)+0.5);
#endif
//#define sqrt_27_bit
/**
Целочисленный алгорит вычисления корня \f$ y = \sqrt{x} \f$.
** алгоритм с плав. зап. взят IAR\ARM\src\lib\dlib\xxsqrt.h
** для sh_sqrt=10 погрешность sqrt( 0 < x < 4) не более 0.004
** для sh_sqrt=12 погрешность sqrt( 0 < x < 4) не более 0.001
@param x - целое положительное число, из которого вычисляется корень
@return Результат вычисления корня
*/
quint32 sqrt_PoMe(quint32 x){ // x - с ц.р. = 2**-sh_sqrt
int exp;
x = norm_x_PoMe(x,&exp); // нормировка 1.0<= x <=4.0 для сходимости, exp кратна 2
int y1;
y1 =( ( (K_sqrt2 - ((K_sqrt1*x)>>sh_sqrt)) * x ) >> sh_sqrt ) + K_sqrt3;
exp=exp/2-sh_sqrt/2;
if (exp>0) return y1<<exp;
else return y1>>(-exp);
}
const quint16 Power2[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096};
const quint16 SizePower2 = 13;
/**
Функция нахождения ближайшего большего или равного числа, являющегося степенью двойки.
@todo Перейти на __CLZ
@param x
@return Степень, в которую требуется возвести 2, чтоб получить искомое число
*/
quint32 NearestPower2(quint32 x){//// Ближайшее большее или равное x число 2^n (возвращаем n)
int i;
if (x >= Power2[SizePower2-1]) return SizePower2-1; // Граничные условия
for (i=0; i<SizePower2; i++){
if (x <= Power2[i]) // Первое число в последовательности, которое привысит или будет равно x
return i; // и будет ответом
}
return 0;
}
#define POWERMEASURE_H_
#ifndef RECEIVER_ALPACA
#define RECEIVER_ALPACA 1 // Альпака
#endif
#ifndef RECEIVER_NIIKP_ARM
#define RECEIVER_NIIKP_ARM 2 // НИИ КП'шный проект
#endif
#ifndef RECEIVER_TYPE
#define RECEIVER_TYPE RECEIVER_NIIKP_ARM
#endif
#include "types.h" // Определяет типы переменных q*
/** Структура данных блока измерения эквивалентного отношения сигнал/шум
для одного корреляционного канала. */
typedef struct {
quint32 x_A2_est[1]; ///< Вектор состояния Ф СС за квадратом амплитуды КК, оценка=экстраполяция
quint32 x_A_est; ///< Оценка амплитуды
quint32 x_stdn2_est; ///< Оценка дисперсии КК
quint32 x_stdn2_est_shifted; ///< Вектор состояния Ф СС за дисперсией КК, оценка=экстраполяция, сдвинут влево
/** @name Аккумуляторы и их триггеры */
quint32 R2; ///< Первичный акк. \f$ I^2 + Q^2 \f$
quint64 R4; ///< Первичный акк. \f$ (I^2 + Q^2)^2 \f$
quint32 R2_acum; ///< Вторичный аккумулятор R2
quint64 R4_acum; ///< Вторичный аккумулятор R4
quint32 R2_acum_copy; ///< Триггер R2_acum
quint64 R4_acum_copy; ///< Триггер R4_acum
//@}
/** @name Счетчики для аккумуляторов */
quint16 sum_counter; ///< для R2, R4
quint16 acum_counter; ///< для R2_acum, R4_acum
//@}
/** @name Пороги накоплений R2_acum, R4_acum */
quint16 acum_threshold;
quint16 acum_threshold_lock;
qint16 acum_threshold_level;
qint16 acum_threshold_level_first;
//@}
quint16 fail_counter; ///< Число подряд идущих срывов измерения амплитуды (комплексные корни)
quint32 start_counter; ///< Счетчик тактов от начала включения блока
quint8 allow_stnd2_est; ///< Разрешить оценивать и фильтровать дисперсию квадратур
int Accumulators_are_ready; ///< Флаг готовности триггеров R2_acum_copy, R4_acum_copy и копия счетчика в одном лице
#if (RECEIVER_TYPE == RECEIVER_ALPACA)
/** @name Сохраненные измерения, поступающие на вход фильтров */
quint32 SQ_A_izm; ///< Квадрата амплитуды
quint32 SQ_stdn_izm; ///< Квадрата СКО
//@}
quint32 qcno; ///< Оценка отношения с/ш, в абсолютных единицах
double qcno_dBHz; ///< Оценка отношения с/ш, в дБГц
double qcno_dBHz_extr; ///< Экстраполяция на следующий такт отношения с/ш, в дБГц
#endif
quint32 IQ_Power; ///< Оценка \f$ E[I^2 + Q^2] \f$
} PowerMeasure_struct;
#if (RECEIVER_TYPE == RECEIVER_ALPACA)
#define PoMe_sum_counter_max 128 ///< Число суммирований в аккумуляторах R2, R4
#define PoMe_obr_Kf_stdn_0 256 ///< Обратный коэффициент Ф СС за дисперсией КК
/**
I,Q in signed short =>
- log2((2^15)^2 * 2 / 2^6 * 128) = 32
- log2((2^15)^4 * 2 / 2^6 * 128) = 64
U2_SHIFT <-> :
- 1) log2(max U^2 >> U2_SHIFT) < 32
- 2) log2(max U^4 >> U2_SHIFT) < 64
- 3) PoMe_sum_counter_max < max_acum_counter (if hasn't reserve in 1) and 2) )
- 4) min U^2 >> U2_SHIFT > 0
Estimates of stdn2 and A2 are shifted by U2_SHIFT relative real values.
*/
#define U2_SHIFT 6 ///< Сдвиг I^2+Q^2 перед аккумулированием
#define PoMe_NoiseU2Bit (20) ///< Typical \f$ \log_2(Noise^2) \f$, exponent of two
#define PoMe_NoiseU2Bit_shifted (PoMe_NoiseU2Bit-U2_SHIFT) ///< PoMe_NoiseU2Bit-U2_SHIFT
#define x_stdn2_shift = (8); ///< Сдвиг дисперсии квадратур во внутренней структуре фильтра
/** @name Делитель вторичных аккумуляторов для каждого времени накопления, сдвиги */
#define PoMe_Threshold_5_sh 1 // Период: 2*PoMe_sum_counter_max
#define PoMe_Threshold_4_sh 2 // 4*PoMe_sum_counter_max
#define PoMe_Threshold_3_sh 3 // 8*PoMe_sum_counter_max
#define PoMe_Threshold_2_sh 5 // 32*PoMe_sum_counter_max
#define PoMe_Threshold_1_sh 6 // 64*PoMe_sum_counter_max
#define PoMe_Threshold_def_sh 5 // 32*PoMe_sum_counter_max
//@}
/** @name Делитель вторичных аккумуляторов для каждого времени накопления */
#define PoMe_Threshold_5 (1<<PoMe_Threshold_5_sh)
#define PoMe_Threshold_4 (1<<PoMe_Threshold_4_sh)
#define PoMe_Threshold_3 (1<<PoMe_Threshold_3_sh)
#define PoMe_Threshold_2 (1<<PoMe_Threshold_2_sh)
#define PoMe_Threshold_1 (1<<PoMe_Threshold_1_sh)
#define PoMe_Threshold_def (1<<PoMe_Threshold_def_sh)
//@}
#define PoMe_Tcorr 0.001 ///< For qcno_dBHz calculation - длительность одного такта Ф
/** "Число лидирующих нулей" - число первых нулей бинарного представления.
Данная функция реализована рекурсивно для совместимости с ARM НИИ КП
@param x Входное 32-разрядное число
@return Число первых нулей бинарного представления переменной */
int __CLZ(int x);
#else if (RECEIVER_TYPE == RECEIVER_NIIKP_ARM) /*#ifndef NIIKP_ARM_F_*/
const int exp_kARU = 12; ///< Экспонента для переменной kARU ~ обратной крутизны
const int PoMe_sum_counter_max = 128; ///< Число суммирований в аккумуляторах R2, R4
const int PoMe_obr_Kf_stdn_0 = 256; ///< Обратный коэффициент Ф СС за дисперсией КК
const quint16 max_fail_counter = 2; ///< Число разрешенных fail_counter до снятия канала
/**
I,Q in signed short =>
- log2((2^15)^2 * 2 / 2^6 * 128) = 32
- log2((2^15)^4 * 2 / 2^6 * 128) = 64
U2_SHIFT <-> :
- 1) log2(max U^2 >> U2_SHIFT) < 32
- 2) log2(max U^4 >> U2_SHIFT) < 64
- 3) PoMe_sum_counter_max < max_acum_counter (if hasn't reserve in 1) and 2) )
- 4) min U^2 >> U2_SHIFT > 0
Estimates of stdn2 and A2 are shifted by U2_SHIFT relative real values.
*/
const int U2_SHIFT = 0; ///< Сдвиг I^2+Q^2 перед аккумулированием
const qint16 PoMe_NoiseU2Bit = 6; ///< Typical \f$ log_2(Noise^2)\f$, exponent of two
const qint16 PoMe_NoiseU2Bit_shifted = (PoMe_NoiseU2Bit-U2_SHIFT); ///< PoMe_NoiseU2Bit-U2_SHIFT
const qint16 x_stdn2_shift = 8; ///< Сдвиг дисперсии квадратур во внутренней структуре фильтра
/** @name Делитель вторичных аккумуляторов для каждого времени накопления, сдвиги */
const qint16 PoMe_Threshold_5_sh = 2; // 4 (x 128 мс)
const qint16 PoMe_Threshold_4_sh = 3; // 8
const qint16 PoMe_Threshold_3_sh = 4; // 16
const qint16 PoMe_Threshold_2_sh = 4; // 16
const qint16 PoMe_Threshold_1_sh = 5; // 32
const qint16 PoMe_Threshold_def_sh = 5; // 32
//@}
/** @name Делитель вторичных аккумуляторов для каждого времени накопления */
const qint16 PoMe_Threshold_5 = (1<<PoMe_Threshold_5_sh);
const qint16 PoMe_Threshold_4 = (1<<PoMe_Threshold_4_sh);
const qint16 PoMe_Threshold_3 = (1<<PoMe_Threshold_3_sh);
const qint16 PoMe_Threshold_2 = (1<<PoMe_Threshold_2_sh);
const qint16 PoMe_Threshold_1 = (1<<PoMe_Threshold_1_sh);
const qint16 PoMe_Threshold_def = (1<<PoMe_Threshold_def_sh);
//@}
#endif /* if (RECEIVER_TYPE == RECEIVER_NIIKP_ARM) */
void InitPowerMeasure(PowerMeasure_struct *PoMe, quint32 Init_qcno);
void DoPowerMeasure(PowerMeasure_struct *PoMe);
void AccumPowerMeasure(PowerMeasure_struct *PoMe, quint32 U2);
int SetVariancePowerMeasure(PowerMeasure_struct *PoMe, quint32 stdn2_IQ);
void AllowVariancePowerMeasure(PowerMeasure_struct *PoMe);
#endif // POWERMEASURE_H_
[править] Проблемы
Doxygen, во всяком случае мой, некорректно работает с директивами препроцессора #if, #ifdef
и т.п. Пока удается решить эту проблему перечислением в Doxyfile (поле PREDEFINED) значений всех используемых в таких выражениях define'ов.