/**
  ******************************************************************************
  * @file    main.c
  *
  * @brief   Проверка работы всех режимов цифровых компараторов без прерываний.
  *
  *          Запускается циклическое преобразование 1 канала.
  *          После каждого измерение генерируется сигнал прерывания, но сами
  *          прерывания на NVIC не идут,т.к. соответсвующие биты не маскированы.
  *          Включаются 12 компараторов и настраивается каждый в индивидуальный
  *          режим. К каждому компаратору подключен 1 канал.
  *
  *          По немаскированному флагу прерывания секвенсора определяется конец
  *          измерения. Затем выводится результат измерения и все текущие
  *          значения выходных триггеров компараторов.
  *
  *          Компилятор: GCC ARM 4.9.3
  *          Среда: Qt Creator 3.4.2
  *
  * @author  НИИЭТ
  *             - Богдан Колбов (bkolbov), kolbov@niiet.ru
  * @date    23.12.2015
  *
  ******************************************************************************
  * @attention
  *
  * ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО
  * ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ
  * ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ
  * НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ
  * ПРЕДНАЗНАЧЕНО ДЛЯ ОЗНАКОМИТЕЛЬНЫХ ЦЕЛЕЙ И НАПРАВЛЕНО ТОЛЬКО НА
  * ПРЕДОСТАВЛЕНИЕ ДОПОЛНИТЕЛЬНОЙ ИНФОРМАЦИИ О ПРОДУКТЕ, С ЦЕЛЬЮ СОХРАНИТЬ ВРЕМЯ
  * ПОТРЕБИТЕЛЮ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ
  * ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА ПРЯМОЙ ИЛИ КОСВЕННЫЙ УЩЕРБ, ИЛИ
  * ПО ИНЫМ ТРЕБО ВАНИЯМ, ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
  * ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
  *
  * <h2><center>&copy; 2015 ОАО "НИИЭТ"</center></h2>
  ******************************************************************************
  */

#include "niietcm4.h"
#include "retarget.h"

void SystemInit()
{
    // переходим на системную частоту 72МГц
    RCC_PLLAutoConfig(RCC_PLLRef_XI_OSC, 72000000);

    // инициализация printf
    retarget_init();

    // хак, чтобы избежать зависших секвенсоров от выставленных запросов по 0 каналу
    // цифровыми компараторами.
    for (uint32_t i = 0; i < 24; i++)
    {
        ADC_DC_DeInit((ADC_DC_Module_TypeDef)i);
    }

    // включаем тактирование 0-модуля ацп (0 и 1 каналы)
    // делим системную частоту на 6, и получаем тактирование АЦП 12МГц.
    RCC_ADCClkDivConfig(RCC_ADCClk_0, 2, ENABLE);
    RCC_PeriphClkCmd(RCC_PeriphClk_ADC, ENABLE);
    RCC_ADCClkCmd(RCC_ADCClk_0, ENABLE);

    // настройка модуля АЦП
    ADC_Init_TypeDef ADC_InitStruct;
    ADC_StructInit(&ADC_InitStruct);
    ADC_InitStruct.ADC_Resolution = ADC_Resolution_12bit;
    ADC_InitStruct.ADC_Average = ADC_Average_64;
    ADC_InitStruct.ADC_Mode = ADC_Mode_Active;
    ADC_InitStruct.ADC_Phase = 0x100;
    ADC_Init(ADC_Module_0, &ADC_InitStruct);
    // включение модуля АЦП
    ADC_Cmd(ADC_Module_0, ENABLE);

    // настройка компараторов
    ADC_DC_Init_TypeDef ADC_DC_Initstruct;
    ADC_DC_Initstruct.ADC_DC_Channel = ADC_DC_Channel_1; // подключаем выход 1 канала ацп
    ADC_DC_Initstruct.ADC_DC_ThresholdLow = 512;
    ADC_DC_Initstruct.ADC_DC_ThresholdHigh = 1024;
    // компаратор 0
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_Single;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_Low;
    ADC_DC_Init(ADC_DC_Module_0, &ADC_DC_Initstruct);
    // компаратор 1
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_Multiple;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_Low;
    ADC_DC_Init(ADC_DC_Module_1, &ADC_DC_Initstruct);
    // компаратор 2
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_SingleHyst;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_Low;
    ADC_DC_Init(ADC_DC_Module_2, &ADC_DC_Initstruct);
    // компаратор 3
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_MultipleHyst;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_Low;
    ADC_DC_Init(ADC_DC_Module_3, &ADC_DC_Initstruct);
    // компаратор 4
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_Single;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_Window;
    ADC_DC_Init(ADC_DC_Module_4, &ADC_DC_Initstruct);
    // компаратор 5
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_Multiple;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_Window;
    ADC_DC_Init(ADC_DC_Module_5, &ADC_DC_Initstruct);
    // компаратор 6
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_SingleHyst;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_Window;
    ADC_DC_Init(ADC_DC_Module_6, &ADC_DC_Initstruct);
    // компаратор 7
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_MultipleHyst;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_Window;
    ADC_DC_Init(ADC_DC_Module_7, &ADC_DC_Initstruct);
    // компаратор 8
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_Single;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_High;
    ADC_DC_Init(ADC_DC_Module_8, &ADC_DC_Initstruct);
    // компаратор 9
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_Multiple;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_High;
    ADC_DC_Init(ADC_DC_Module_9, &ADC_DC_Initstruct);
    // компаратор 10
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_SingleHyst;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_High;
    ADC_DC_Init(ADC_DC_Module_10, &ADC_DC_Initstruct);
    // компаратор 11
    ADC_DC_Initstruct.ADC_DC_Mode = ADC_DC_Mode_MultipleHyst;
    ADC_DC_Initstruct.ADC_DC_Condition = ADC_DC_Condition_High;
    ADC_DC_Init(ADC_DC_Module_11, &ADC_DC_Initstruct);

    ADC_DC_Cmd(ADC_DC_Module_0, ENABLE);
    ADC_DC_Cmd(ADC_DC_Module_1, ENABLE);
    ADC_DC_Cmd(ADC_DC_Module_2, ENABLE);
    ADC_DC_Cmd(ADC_DC_Module_3, ENABLE);
    ADC_DC_Cmd(ADC_DC_Module_4, ENABLE);
    ADC_DC_Cmd(ADC_DC_Module_5, ENABLE);
    ADC_DC_Cmd(ADC_DC_Module_6, ENABLE);
    ADC_DC_Cmd(ADC_DC_Module_7, ENABLE);
    ADC_DC_Cmd(ADC_DC_Module_8, ENABLE);
    ADC_DC_Cmd(ADC_DC_Module_9, ENABLE);
    ADC_DC_Cmd(ADC_DC_Module_10, ENABLE);
    ADC_DC_Cmd(ADC_DC_Module_11, ENABLE);

    // секвенсор 0 работает циклически
    ADC_SEQ_Init_TypeDef ADC_SEQ_InitStruct;
    ADC_SEQ_StructInit(&ADC_SEQ_InitStruct);
    ADC_SEQ_InitStruct.ADC_SEQ_StartEvent = ADC_SEQ_StartEvent_Cycle;
    ADC_SEQ_InitStruct.ADC_Channels = ADC_Channel_1;
    ADC_SEQ_InitStruct.ADC_SEQ_DC = ADC_DC_0 | ADC_DC_1 | ADC_DC_2 | ADC_DC_3 |
                                    ADC_DC_4 | ADC_DC_5 | ADC_DC_6 | ADC_DC_7 |
                                    ADC_DC_8 | ADC_DC_9 | ADC_DC_10| ADC_DC_11;
    ADC_SEQ_InitStruct.ADC_SEQ_ConversionDelay = 0xFFFFFF; // делаем большую задержку, чтобы курсор быстро не убегал вниз при выводе
    ADC_SEQ_Init(ADC_SEQ_Module_0, &ADC_SEQ_InitStruct);
}

int main()
{

    printf("\n\nStart!\n\n");

    printf("All DC low  threshold (COMP0): %04d\n", NT_ADC->DCCMP_bit[0].COMP0);
    printf("All DC high threshold (COMP1): %04d\n", NT_ADC->DCCMP_bit[0].COMP1);
    printf("M  - multiple\n");
    printf("S  - single\n");
    printf("MH - multiple with hysteresis\n");
    printf("SH - single with hysteresis\n\n");

    printf(" _____ ___________________________________________________________\n");
    printf("|     |   LOW CONDITION   | WINDOW CONDITION  |  HIGH CONDITION   |\n");
    printf("|     |___________________|___________________|___________________|\n");
    printf("|     |  S |  M | SH | MH |  S |  M | SH | MH |  S |  M | SH | MH |\n");
    printf("|_____|____|____|____|____|____|____|____|____|____|____|____|____|\n");
    printf("|  MSR|DC00|DC01|DC02|DC03|DC04|DC05|DC06|DC07|DC08|DC09|DC10|DC11|\n");
    printf("|_____|____|____|____|____|____|____|____|____|____|____|____|____|\n");

    // включаем секвенсор, циклические измерения сразу же начнутся
    ADC_SEQ_Cmd(ADC_SEQ_Module_0, ENABLE);

    while(1)
    {
        if (ADC_SEQ_ITRawStatus(ADC_SEQ_Module_0)) // флаг завершения преобразования
        {
            ADC_SEQ_ITStatusClear(ADC_SEQ_Module_0);
            printf("| %04d|  %1d |  %1d |  %1d |  %1d |  %1d |  %1d |  %1d |  %1d |  %1d |  %1d |  %1d |  %1d |\n",
                   ADC_SEQ_GetFIFOData(ADC_SEQ_Module_0),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_0),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_1),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_2),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_3),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_4),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_5),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_6),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_7),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_8),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_9),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_10),
                   (uint32_t)ADC_DC_TrigStatus(ADC_DC_Module_11));
            printf("|_____|____|____|____|____|____|____|____|____|____|____|____|____|\n");

            // сбрасываем выходные триггеры компараторов
            ADC_DC_TrigStatusClear(ADC_DC_Module_0);
            ADC_DC_TrigStatusClear(ADC_DC_Module_1);
            ADC_DC_TrigStatusClear(ADC_DC_Module_2);
            ADC_DC_TrigStatusClear(ADC_DC_Module_3);
            ADC_DC_TrigStatusClear(ADC_DC_Module_4);
            ADC_DC_TrigStatusClear(ADC_DC_Module_5);
            ADC_DC_TrigStatusClear(ADC_DC_Module_6);
            ADC_DC_TrigStatusClear(ADC_DC_Module_7);
            ADC_DC_TrigStatusClear(ADC_DC_Module_8);
            ADC_DC_TrigStatusClear(ADC_DC_Module_9);
            ADC_DC_TrigStatusClear(ADC_DC_Module_10);
            ADC_DC_TrigStatusClear(ADC_DC_Module_11);
        }
    }
}
