#include "at32f403a_407.h"
#include "mux.h"
#include "FreeRTOS.h"
#include "task.h"
#include <stdbool.h>


void mux_task(void *argument);


/* -------------------------------------------------------------------------- */
#if defined (MDIO_88)
mux_channel_t leds[LED_NUMBER] = {
                                  {INP_1, {0, 0, 0}, LED_OFF, 0},
                                  {INP_2, {0, 0, 0}, LED_OFF, 0},
                                  {INP_3, {0, 0, 0}, LED_OFF, 0},
                                  {INP_4, {0, 0, 0}, LED_OFF, 0},

                                  {INP_5, {0, 1, 1}, LED_OFF, 0},
                                  {INP_6, {0, 1, 1}, LED_OFF, 0},
                                  {INP_7, {0, 1, 1}, LED_OFF, 0},
                                  {INP_8, {0, 1, 1}, LED_OFF, 0},
                                  
                                  {OUT_1_G, {1, 0, 0}, LED_OFF, 0},
                                  {OUT_2_G, {1, 0, 0}, LED_OFF, 0},
                                  {OUT_3_G, {1, 0, 0}, LED_OFF, 0},
                                  {OUT_4_G, {1, 0, 0}, LED_OFF, 0},
                                  
                                  {OUT_1_R, {0, 1, 0}, LED_OFF, 0},
                                  {OUT_2_R, {0, 1, 0}, LED_OFF, 0},
                                  {OUT_3_R, {0, 1, 0}, LED_OFF, 0},
                                  {OUT_4_R, {0, 1, 0}, LED_OFF, 0},

                                  {STATUS_G, {1, 1, 0}, LED_OFF, 0},
                                  {STATUS_R, {1, 1, 0}, LED_OFF, 0},
                                  {RX_G, {1, 1, 0}, LED_OFF, 0},
                                  {TX_R, {1, 1, 0}, LED_OFF, 0},
                                  
                                  {OUT_5_R, {0, 0, 1}, LED_OFF, 0},
                                  {OUT_6_R, {0, 0, 1}, LED_OFF, 0},
                                  {OUT_7_R, {0, 0, 1}, LED_OFF, 0},
                                  {OUT_8_R, {0, 0, 1}, LED_OFF, 0},

                                  {OUT_5_G, {1, 0, 1}, LED_OFF, 0},
                                  {OUT_6_G, {1, 0, 1}, LED_OFF, 0},
                                  {OUT_7_G, {1, 0, 1}, LED_OFF, 0},
                                  {OUT_8_G, {1, 0, 1}, LED_OFF, 0}
                                 };
/* -------------------------------------------------------------------------- */
#elif defined (MAI_12)

/*uint8_t         line[3];    // [line_0, line_1, line_2]*/
mux_channel_t leds[LED_NUMBER] = {
                                  {IO_1_G, {0, 0, 0}, LED_OFF, 0},
                                  {IO_1_R, {0, 0, 0}, LED_OFF, 0},
                                  {IO_2_G, {0, 0, 0}, LED_OFF, 0},
                                  {IO_2_R, {0, 0, 0}, LED_OFF, 0},
                                  
                                  {IO_3_G, {1, 0, 0}, LED_OFF, 0},
                                  {IO_3_R, {1, 0, 0}, LED_OFF, 0},
                                  {IO_4_G, {1, 0, 0}, LED_OFF, 0},
                                  {IO_4_R, {1, 0, 0}, LED_OFF, 0},
                                  
                                  {IO_5_G, {0, 1, 0}, LED_OFF, 0},
                                  {IO_5_R, {0, 1, 0}, LED_OFF, 0},
                                  {IO_6_G, {0, 1, 0}, LED_OFF, 0},
                                  {IO_6_R, {0, 1, 0}, LED_OFF, 0},
                                  
                                  {STATUS_G, {1, 1, 0}, LED_OFF, 0},
                                  {STATUS_R, {1, 1, 0}, LED_OFF, 0},
                                  {RX_G, {1, 1, 0}, LED_OFF, 0},
                                  {TX_R, {1, 1, 0}, LED_OFF, 0},
                                  
                                  {IO_7_G, {0, 0, 1}, LED_OFF, 0},
                                  {IO_7_R, {0, 0, 1}, LED_OFF, 0},
                                  {IO_8_G, {0, 0, 1}, LED_OFF, 0},
                                  {IO_8_R, {0, 0, 1}, LED_OFF, 0},
                                  
                                  {IO_9_G, {1, 0, 1}, LED_OFF, 0},
                                  {IO_9_R, {1, 0, 1}, LED_OFF, 0},
                                  {IO_10_G, {1, 0, 1}, LED_OFF, 0},
                                  {IO_10_R, {1, 0, 1}, LED_OFF, 0},
                                  
                                  {IO_11_G, {0, 1, 1}, LED_OFF, 0},
                                  {IO_11_R, {0, 1, 1}, LED_OFF, 0},
                                  {IO_12_G, {0, 1, 1}, LED_OFF, 0},
                                  {IO_12_R, {0, 1, 1}, LED_OFF, 0},
};

#else
//# defined (MAO_8)
mux_channel_t leds[1] = {
                                  {INP_1, {0, 0, 0}, LED_OFF, 0},
                                 };
#endif

//
void mux_led_init(mux_channel_t *ch)
{
}


//
void mux_gpio_init(void)
{
    gpio_init_type gpio_initstructure;
  
    
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE);
    
    // LED_COL
    //      COL_1 - PD6
    //      COL_2 - PD7
    //      COL_3 - PB6
    //      COL_4 - PB7
    gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;  
    gpio_initstructure.gpio_pull           = GPIO_PULL_NONE;  
    gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;  
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_initstructure.gpio_pins           = GPIO_PINS_6 | GPIO_PINS_7;
    gpio_init(GPIOB, &gpio_initstructure); 

    gpio_initstructure.gpio_pins           = GPIO_PINS_6 | GPIO_PINS_7;
    gpio_init(GPIOD, &gpio_initstructure); 
    
    gpio_bits_reset(GPIOB, GPIO_PINS_6 | GPIO_PINS_7);
    gpio_bits_reset(GPIOD, GPIO_PINS_6 | GPIO_PINS_7);
    
    // LED_LINE (низкий уровень на пине = высокий уровень на входе MUX)
    //      LINE_0 - PE3
    //      LINE_1 - PE2
    //      LINE_2 - PB9
    gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;  
    gpio_initstructure.gpio_pull           = GPIO_PULL_NONE;  
    gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;  
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_initstructure.gpio_pins           = GPIO_PINS_2 | GPIO_PINS_3;
    gpio_init(GPIOE, &gpio_initstructure); 

    gpio_initstructure.gpio_pins           = GPIO_PINS_9;
    gpio_init(GPIOB, &gpio_initstructure);
    
    gpio_bits_reset(GPIOE, GPIO_PINS_2 | GPIO_PINS_3);
    gpio_bits_reset(GPIOB, GPIO_PINS_9);
}


//
void mux_led_proc(void)
{
    uint8_t shift = 0;
    bool flag = false;
    
    for (uint8_t i = 0; i < LED_NUMBER/4; i++)
    {
        leds[shift].line[0] ? (LINE_0_RESET) : (LINE_0_SET);
        leds[shift].line[1] ? (LINE_1_RESET) : (LINE_1_SET);
        leds[shift].line[2] ? (LINE_2_RESET) : (LINE_2_SET);
        
        leds[i*4].state     == LED_ON ? (COL_1_SET) : (COL_1_RESET);
        leds[i*4 + 1].state == LED_ON ? (COL_2_SET) : (COL_2_RESET);
        leds[i*4 + 2].state == LED_ON ? (COL_3_SET) : (COL_3_RESET);
        leds[i*4 + 3].state == LED_ON ? (COL_4_SET) : (COL_4_RESET);

#if 1        
        if (leds[i*4].state == LED_ON || leds[i*4 + 1].state == LED_ON || 
            leds[i*4 + 2].state == LED_ON || leds[i*4 + 3].state == LED_ON) 
        {
            flag = true;
            vTaskDelay(1);
        }
        
#endif        
        shift += 4;
    }
    
    if (!flag)
        vTaskDelay(1);
}

//
void mux_led_test_init(void)
{
    LINE_0_SET;
    LINE_1_SET;
    LINE_2_SET;
}

//
void mux_led_test_toggle(void)
{
    static bool flag = false;
    
    if (!flag) {
        COL_1_SET;
        flag = true;
    }
    else {
        COL_1_RESET;
        flag = false;
    }
}

//
void mux_led_blink(void)
{
    for (int i = 0; i < LED_NUMBER; i++)
    {
        leds[i].state = LED_ON;
        
        vTaskDelay(100);
        
        leds[i].state = LED_OFF;
    }
}

// true - normal
// false - alarm
void mux_led_status(bool state)
{
/*  
    if (state) {
        leds[STATUS_G].state = LED_ON;
        leds[STATUS_R].state = LED_OFF;
    }
    else {
        leds[STATUS_G].state = LED_OFF;
        leds[STATUS_R].state = LED_ON;
    }
*/    
}

//
void mux_task(void *argument)
{
    for (;;)
    {
        mux_led_proc();
    }
}
