#include "at32f403a_407.h"
#include "analog_output.h"
#include "shift_reg.h"
#include "utility.h"
#include "FreeRTOS.h"
#include "task.h"
#include "settings_api.h"
#include "dac_transport.h"
#include "monitoring.h"
#include "mux.h"
#include "io_utils.h"
#include <stdio.h>

#undef DBG
#define DBG if(0)

#if defined (MAO_4)


uint16_t ao_mode;   // режим работы аналоговый

uint16_t ao_power;  // слово состояния питания выходных каналов

static bool set_value_flag = false; // 

led_t ao_output_led[4] = {OUT_1_G, OUT_2_G, OUT_3_G, OUT_4_G};



//
void ao_init(void)
{
  
#if 0  
    // Для тестов
    settings.ao[0].state = 1;
    settings.ao[1].state = 1;
    settings.ao[2].state = 0;
    settings.ao[3].state = 0;
    
    settings.ao[0].value = 30000;
    settings.ao[1].value = 30000;
    settings.ao[2].value = 30000;
    settings.ao[3].value = 30000;
    
    settings.ao_save[0].state = 0;
    settings.ao_save[1].state = 0;
    settings.ao_save[2].state = 1;
    settings.ao_save[3].state = 1;
    
    settings.ao_save[0].value = 50000;
    settings.ao_save[1].value = 50000;
    settings.ao_save[2].value = 50000;
    settings.ao_save[3].value = 50000;
#endif    
    
    // Обновление состояний LED
    // Зеленые LED сигнализируют (вкл/выкл) входов. Проверка на безопасный режим.
    if (save_mode_get())
        ao_led_update(settings.ao_save);
    else 
        ao_led_update(settings.ao);
    
    // Сдвиговые регистры
    sh_init();
    
    // Внешний DAC
    dac_init();
    
    // Режир работы выходов.
    // При старте проверяется состояние безопасного режима в настройках
    if (save_mode_get()) {
        ao_mode = settings.ao_mode_save_bits;
    }
    else {
        ao_mode = settings.ao_mode_bits;
    }
    
    // Флаг - нужно обновить значения на выходах
    ao_set_value_flag();
}

// Вызывается при обновлении статуса безопасного режима работы
void ao_save_update(bool state)
{
    if (state) {
        ao_led_update(settings.ao_save);
    }
    else {
        ao_led_update(settings.ao);
    }
        
    ao_set_value_flag();
}

// Управление LED для выходов
void ao_led_update(ao_t *ao)
{
    for (int i = 0; i < AO_NUMBER; i++) 
    {
        if (ao[i].state)
            leds[ao_output_led[i]].state = LED_ON;
        else
            leds[ao_output_led[i]].state = LED_OFF;
    }
}

// Включение/выключение каналов
void ao_set(void)
{
    for (int i = 0; i < AO_NUMBER; i++)
    {
        settings.ao[i].state = (uint8_t)((settings.ao_state_bits >> i) & 1);

        if (settings.ao[i].state == 0) {
            leds[ao_output_led[i]].state = LED_OFF;
        }
        else {
            leds[ao_output_led[i]].state = LED_ON;
        }
    }
}

// Включение/выключение каналов (безопасный режим)
void ao_set_save(void)
{
    for (int i = 0; i < AO_NUMBER; i++)
    {
        settings.ao_save[i].state = (uint8_t)((settings.ao_state_save_bits >> i) & 1);
    }
}         
         
// Установить режим работы каналов
void ao_set_mode(void)
{
    for (int i = 0; i < AO_NUMBER; i++)
    {
        settings.ao[i].mode = (uint8_t)((settings.ao_mode_bits >> i) & 1);
    }
}

// Установить режим работы каналов (безопасный режим)
void ao_set_mode_save(void)
{
    for (int i = 0; i < AO_NUMBER; i++)
    {
        settings.ao_save[i].mode = (uint8_t)((settings.ao_mode_save_bits >> i) & 1);
    }
}

//
void ao_set_value_flag(void)
{
    set_value_flag = true;
}

//
void ao_set_values(ao_t *ao)
{
    for (int i = 0; i < AO_NUMBER; i++)
    {
        if (ao[i].state) {
            dac_test((DAC_CHANNEL)i, ao[i].value);
        }
        else {
            dac_test((DAC_CHANNEL)i, 0);
        }
    }
}

// 
void dac_task(void *params)
{
    for (;;)
    {   
        // 
        ao_power = sh_ao_mode(ao_mode);
        
        // Обновить значения на выходах
        // Нужно проверять наличие безопасного режима работы
        if (set_value_flag)
        {
            set_value_flag = false;
            
            if (save_mode_get()) {
                ao_set_values(settings.ao_save);
            }
            else {
                ao_set_values(settings.ao);
            }
        }
        
        
        //ao_set_values(settings.ao_save);
        
        DBG printf("AO_Power: %u\r\n", ao_power);
        
        vTaskDelay(100);
    }
}

#endif