#include "at32f403a_407.h"
#include "common_gpio.h"
#include "FreeRTOS.h"
#include "task.h"
#include "io.h"
#include <stdbool.h>


#define ADDR_PIN_NUM    4

#define HW_REV_PIN_NUM  3


uint16_t board_rev;


//
din_t addr_in[ADDR_PIN_NUM] = {
    {GPIOC, GPIO_PINS_4, 0, 0, false, 0}, // 1   
    {GPIOA, GPIO_PINS_7, 0, 0, false, 0}, // 2
    {GPIOA, GPIO_PINS_6, 0, 0, false, 0}, // 3 
    {GPIOA, GPIO_PINS_5, 0, 0, false, 0}, // 4 
};

//
din_t rev_in[ADDR_PIN_NUM] = {
    {GPIOE, GPIO_PINS_7, 0, 0, false, 0}, // 1   
    {GPIOE, GPIO_PINS_8, 0, 0, false, 0}, // 2
    {GPIOE, GPIO_PINS_9, 0, 0, false, 0}, // 3 
};



//
void gpio_wdt_init(void)
{
    gpio_init_type gpio_initstructure;
        
    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
    
    // WDT
    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_7;
    gpio_init(GPIOC, &gpio_initstructure); 
}

// Пины переключателя modbus-адреса
void gpio_mbaddr_init(void)
{
    gpio_init_type gpio_init_struct;

    gpio_default_para_init(&gpio_init_struct);
        
    for (uint8_t i = 0; i < ADDR_PIN_NUM; i++)
    {
        gpio_init_struct.gpio_pull           = GPIO_PULL_UP;  
        gpio_init_struct.gpio_mode           = GPIO_MODE_INPUT;  
        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
        gpio_init_struct.gpio_pins           = addr_in[i].pin ;
        gpio_init(addr_in[i].port, &gpio_init_struct);
    }
}

//
uint8_t gpio_get_mbaddr(void)
{
    uint8_t ret = 0;
    
    for (uint8_t i = 0; i < ADDR_PIN_NUM; i++)
    {
        ret |= ((uint8_t)!gpio_input_data_bit_read(addr_in[i].port, addr_in[i].pin) << i);
    }
    
    ret = ret > 1 ? ret : 1;
        
    return ret;
}

//
bool gpio_check_mbaddr(uint8_t old_addr, uint8_t *new_addr)
{
    uint8_t tmp = gpio_get_mbaddr();
    
    if (old_addr != tmp)
    {
        *new_addr = tmp;
        return true;
    }
    return false;
}

// Считать ревизию платы
// Уточнить пины PE7, PE8, PE9
void gpio_update_rev(void)
{
    board_rev = 0;
    
    gpio_init_type gpio_init_struct;

    gpio_default_para_init(&gpio_init_struct);
        
    for (uint8_t i = 0; i < HW_REV_PIN_NUM; i++)
    {
        gpio_init_struct.gpio_pull           = GPIO_PULL_UP;  
        gpio_init_struct.gpio_mode           = GPIO_MODE_INPUT;  
        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
        gpio_init_struct.gpio_pins           = rev_in[i].pin ;
        gpio_init(rev_in[i].port, &gpio_init_struct);
    }
    
    for (uint8_t i = 0; i < HW_REV_PIN_NUM; i++)
    {
        board_rev |= (uint8_t)gpio_input_data_bit_read(rev_in[i].port, rev_in[i].pin) << i;
    }
}

//
uint16_t gpio_get_board_rev(void)
{
    return board_rev;
}

//
void extern_wdt_togle(void)
{
    static bool toogle = false;
    
    if (!toogle) {
        toogle = true;
        gpio_bits_set(GPIOC, GPIO_PINS_7);
    }
    else {
        toogle = false;
        gpio_bits_reset(GPIOC, GPIO_PINS_7);
    }
}