#include <includes.h>
#include "control.h"
#include "data.h"
#include "datadesc.h"
#include <stdlib.h>
#include <string.h>

#if defined(BOARD_SOLARIUM_VLAD)

CPU_INT08U control_initialized = 0;
CPU_INT08U control_state[CHANNELS_NUM];
CPU_INT16U control_counters[CHANNELS_NUM];
CPU_INT08U control_channels[CHANNELS_NUM] = {0, 1, 2};

#define CTRL_GPIO_OFF    0
#define CTRL_GPIO_ON     1

///
inline void set_gpio(CPU_INT08U ch, CPU_INT08U lamp, CPU_INT08U vent)
{
    if (ch == CHANNEL_1)
    {
        if (lamp) FIO3SET_bit.P3_25 = 1;
        else FIO3CLR_bit.P3_25 = 1;
        if (vent) FIO1SET_bit.P1_19 = 1;
        else FIO1CLR_bit.P1_19 = 1;
    }
    else if (ch == CHANNEL_2)
    {
        if (lamp) FIO2SET_bit.P2_2 = 1;
        else FIO2CLR_bit.P2_2 = 1;
        if (vent) FIO0SET_bit.P0_4 = 1;
        else FIO0CLR_bit.P0_4 = 1;
    }
    else if (ch == CHANNEL_3)
    {
        if (lamp) FIO1SET_bit.P1_27 = 1;
        else FIO1CLR_bit.P1_27 = 1;
        if (vent) FIO0SET_bit.P0_0 = 1;
        else FIO0CLR_bit.P0_0 = 1;
    }
}

void SetControl(CPU_INT08U ch, CPU_INT08U state)
{
    CPU_INT08U tmp = control_channels[ch];
    if (tmp < CHANNELS_NUM)
    {
        ch = tmp;
    }
        
    #if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr = 0;
    #endif
    OS_ENTER_CRITICAL();

    if (state == CONTROL_STATE_OFF)
    {
        control_state[ch] = CONTROL_STATE_OFF;
        control_counters[ch] = 0;
    }
    else if (state == CONTROL_STATE_VENT)
    {
        if (control_state[ch] == CONTROL_STATE_OFF)
        {
            control_state[ch] = state;
        }
    }
    else if (state == CONTROL_STATE_PAUSED)
    {
        if (control_state != CONTROL_STATE_OFF)
        {
            if (control_counters[ch] >= 2000) control_state[ch] = state;
        }
    }
    else
    {
        if (control_state[ch] == CONTROL_STATE_OFF)
        {
            control_state[ch] = state;
            control_counters[ch] = 0;
        }
        else if (control_state[ch] == CONTROL_STATE_PAUSED)
        {
            control_state[ch] = state;
        }
    }

    OS_EXIT_CRITICAL();
}

///
CPU_INT08U GetControlState(CPU_INT08U ch)
{
    CPU_INT08U tmp = control_channels[ch];
    if (tmp < CHANNELS_NUM)
    {
        ch = tmp;
    }
    
    CPU_INT08U state;
    #if OS_CRITICAL_METHOD == 3
    OS_CPU_SR  cpu_sr = 0;
    #endif
    OS_ENTER_CRITICAL();
    state = control_state[ch];
    OS_EXIT_CRITICAL();
    return state;
}

///
void control_1ms_callback(void)
{
    if (!control_initialized) return;
    
    for (CPU_INT08U i = 0; i < CHANNELS_NUM; i++)
    {
        if (control_state[i] != CONTROL_STATE_OFF)
        {
            if (control_counters[i] < 2000) control_counters[i]++;
        }

        if (control_state[i] == CONTROL_STATE_OFF)
        {
            set_gpio(i, CTRL_GPIO_OFF, CTRL_GPIO_OFF);
        }
        else if ((control_state[i] == CONTROL_STATE_PAUSED) || (control_state[i] == CONTROL_STATE_VENT))
        {
            set_gpio(i, CTRL_GPIO_OFF, CTRL_GPIO_ON);
        }
        else
        {
            if (control_counters[i] < 500)
            {
                set_gpio(i, CTRL_GPIO_ON, CTRL_GPIO_ON);
            }
            else if (control_counters[i] < 1000)
            {
                // виброплатформа всегда выкл.
                set_gpio(i, CTRL_GPIO_ON, CTRL_GPIO_ON);
            }
            else if (control_counters[i] < 1500)
            {
                // вкл./выкл. коллатен
                if (control_state[i] != CONTROL_STATE_UF) 
                {
                    set_gpio(i, CTRL_GPIO_ON, CTRL_GPIO_ON);
                }
                else
                {
                    set_gpio(i, CTRL_GPIO_OFF, CTRL_GPIO_ON);
                }
            }
            else if (control_counters[i] < 2000)
            {
                // вкл./выкл. ультрафиолет
                if (control_state[i] != CONTROL_STATE_COLLATEN) 
                {
                    set_gpio(i, CTRL_GPIO_ON, CTRL_GPIO_ON);
                }
                else
                {
                    set_gpio(i, CTRL_GPIO_OFF, CTRL_GPIO_ON);
                }
            }
            else
            {
                set_gpio(i, CTRL_GPIO_ON, CTRL_GPIO_ON);
            }
        }
    }
}

///
void LoadControlChannels(void)
{
    for (CPU_INT08U i = 0; i < CHANNELS_NUM; i++)
    {
        CPU_INT32U index;
        GetData(&SolarControlChannelDesc, &index, i, DATA_FLAG_DIRECT_INDEX);
        if (index > CHANNELS_NUM - 1)
        {
            control_channels[i] = i;
        }
        else
        {
            control_channels[i] = (CPU_INT08U)index;
        }
    }
}
        
///
void InitControls(void)
{
    memset(control_counters, 0, sizeof(control_counters));
    
    PINSEL7_bit.P3_25 = 0x0;
    PINMODE7_bit.P3_25 = 0;
    FIO3DIR_bit.P3_25 = 1;
    FIO3MASK_bit.P3_25 = 0;

    PINSEL3_bit.P1_19 = 0x0;
    PINMODE3_bit.P1_19 = 0;
    FIO1DIR_bit.P1_19 = 1;
    FIO1MASK_bit.P1_19 = 0;
  
    set_gpio(CHANNEL_1, CTRL_GPIO_OFF, CTRL_GPIO_OFF);
    control_state[CHANNEL_1] = CONTROL_STATE_OFF;
    control_counters[CHANNEL_1] = 0;

    PINSEL4_bit.P2_2 = 0x0;
    PINMODE4_bit.P2_2 = 0;
    FIO2DIR_bit.P2_2 = 1;
    FIO2MASK_bit.P2_2 = 0;
    
    PINSEL0_bit.P0_4 = 0x0;
    PINMODE0_bit.P0_4 = 0;
    FIO0DIR_bit.P0_4 = 1;
    FIO0MASK_bit.P0_4 = 0;

    set_gpio(CHANNEL_2, CTRL_GPIO_OFF, CTRL_GPIO_OFF);
    control_state[CHANNEL_2] = CONTROL_STATE_OFF;
    control_counters[CHANNEL_2] = 0;

    PINSEL3_bit.P1_27 = 0x0;
    PINMODE3_bit.P1_27 = 0;
    FIO1DIR_bit.P1_27 = 1;
    FIO1MASK_bit.P1_27 = 0;
  
    PINSEL0_bit.P0_0 = 0x0;
    PINMODE0_bit.P0_0 = 0;
    FIO0DIR_bit.P0_0 = 1;
    FIO0MASK_bit.P0_0 = 0;
  
    set_gpio(CHANNEL_3, CTRL_GPIO_OFF, CTRL_GPIO_OFF);
    control_state[CHANNEL_3] = CONTROL_STATE_OFF;
    control_counters[CHANNEL_3] = 0;
        
    control_initialized = 1;
}

#endif
