#include "at32f403a_407.h"
#include "modbus_params.h"
#include "settings_api.h"
#include "io.h"
#include "uptime.h"
#include "rtc.h"
#include "input.h"
#include "output.h"
#include "log.h"
#include <string.h>


mb_param_t mb_param[MB_PARAM_MAX];

uint32_t rtc_sinhro;

void get_time(uint8_t* buf, uint8_t size);
void get_din_mode(uint8_t* buf, uint8_t size);

void get_log_entries_number(uint8_t* buf, uint8_t size);
void get_archive_entries_number(uint8_t* buf, uint8_t size);




//
void mb_init_params(void)
{
    uint16_t index = 0;
    uint16_t addr = 0;
    
    mb_param[index].reg = 0x0100;
	mb_param[index].size = 1;
	mb_param[index].param = (uint8_t*)&input_state_bit;  // Текущее состояние входа
	mb_param[index].set = NULL;
    mb_param[index].get = NULL;
    mb_param[index].check_handler = mb_check_dummy;
    
    index++;
        
    // Счетчики импульсов. Регистры 0x0102 - 0x0111
    addr = 0x0102;
    for (int i = 0; i < DI_NUMBER; i++)
    {
        mb_param[index].reg = addr;
        mb_param[index].size = 2;
        mb_param[index].param = (uint8_t*)&input_cnt[i];  // Счетчик ипульсов
        mb_param[index].set = NULL;
        mb_param[index].get = NULL;
        mb_param[index].check_handler = mb_check_dummy;
        
        addr += 2;
        index++;
    } 
    
    // Режим работы входов
    mb_param[index].reg = 0x0120;
	mb_param[index].size = 1;
	mb_param[index].param = (uint8_t*)&settings.di_mode_bits;  
	mb_param[index].set = mb_set_din_mode;
    mb_param[index].get = NULL;
    mb_param[index].check_handler = mb_check_dummy;
    
    index++;
    
    // Нормальное состояние входов
    mb_param[index].reg = 0x0122;
	mb_param[index].size = 1;
	mb_param[index].param = (uint8_t*)&settings.di_norm_state_bits;  
	mb_param[index].set = NULL;
    mb_param[index].get = NULL;
    mb_param[index].check_handler = mb_check_dummy;
    
    index++;
 
    // Счетчики импульсов. Регистры 0x0102 - 0x0111
    addr = 0x0124;
    for (int i = 0; i < DI_NUMBER; i++)
    {
        mb_param[index].reg = addr;
        mb_param[index].size = 1;
        mb_param[index].param = (uint8_t*)&settings.di_debounce[i];  // Счетчик ипульсов
        mb_param[index].set = NULL;
        mb_param[index].get = NULL;
        mb_param[index].check_handler = mb_check_dummy;
        
        addr++;
        index++;
    }
    
    // Текущее состояние выходов
    mb_param[index].reg = 0x0200;
	mb_param[index].size = 1;
	mb_param[index].param = (uint8_t*)&output_state_bit;  
	mb_param[index].set = mb_set_do;
    mb_param[index].get = NULL;
    mb_param[index].check_handler = mb_check_dummy;
    
    index++;
    
    // Режим работы выходов
    mb_param[index].reg = 0x0202;
	mb_param[index].size = 1;
	mb_param[index].param = (uint8_t*)&output_mode_bit;  
	mb_param[index].set = mb_set_do_mode;
    mb_param[index].get = NULL;
    mb_param[index].check_handler = mb_check_dummy;
    
    index++;
    
    // Состояние выходов в безопасном режиме
    mb_param[index].reg = 0x0203;
	mb_param[index].size = 1;
	mb_param[index].param = (uint8_t*)&settings.do_save_bits;  
	mb_param[index].set = mb_set_do;
    mb_param[index].get = NULL;
    mb_param[index].check_handler = mb_check_dummy;
    
    index++;
    
    // Заполнение PWM. Регистры 0x0210 - 0x0217
    addr = 0x0210;
    for (int i = 0; i < DO_NUMBER; i++)
    {
        mb_param[index].reg = addr;
        mb_param[index].size = 1;
        mb_param[index].param = (uint8_t*)&output_pwm[i];  // Счетчик ипульсов
        mb_param[index].set = mb_set_do;
        mb_param[index].get = NULL;
        mb_param[index].check_handler = mb_check_dummy;
        
        addr++;
        index++;
    }
    
    // Заполнение PWM в безопасном режиме. Регистры 0x0220 - 0x0227
    addr = 0x0220;
    for (int i = 0; i < DO_NUMBER; i++)
    {
        mb_param[index].reg = addr;
        mb_param[index].size = 1;
        mb_param[index].param = (uint8_t*)&output_pwm_save[i];  // Счетчик ипульсов
        mb_param[index].set = mb_set_do;
        mb_param[index].get = NULL;
        mb_param[index].check_handler = mb_check_dummy;
        
        addr++;
        index++;
    }
    
    // Период PWM. Регистры 0x0220 - 0x0227
    addr = 0x0230;
    for (int i = 0; i < DO_NUMBER; i++)
    {
        mb_param[index].reg = addr;
        mb_param[index].size = 1;
        mb_param[index].param = (uint8_t*)&output_pwm_period[i];  // Счетчик ипульсов
        mb_param[index].set = mb_set_do;
        mb_param[index].get = NULL;
        mb_param[index].check_handler = mb_check_dummy;
        
        addr++;
        index++;
    }
    
    // Период PWM. Регистры 0x0220 - 0x0227
    addr = 0x0240;
    for (int i = 0; i < DO_NUMBER; i++)
    {
        mb_param[index].reg = addr;
        mb_param[index].size = 1;
        mb_param[index].param = (uint8_t*)&output_pwm_period_save[i];  // Счетчик ипульсов
        mb_param[index].set = mb_set_do;
        mb_param[index].get = NULL;
        mb_param[index].check_handler = mb_check_dummy;
        
        addr++;
        index++;
    }
    
    // Журналы/рахивы
    
    // Емкость журнала (максимальная)
    mb_param[index].reg = 0x0900;
	mb_param[index].size = 1;
	mb_param[index].param = (uint8_t*)&log_entries_capacity; // 
	mb_param[index].set = NULL;
    mb_param[index].get = NULL;
    mb_param[index].check_handler = mb_check_dummy;
    
    index++;
    
    // Текущее количество записей в журнале
    mb_param[index].reg = 0x0901;
	mb_param[index].size = 1;
	mb_param[index].param = NULL; // 
	mb_param[index].set = NULL;
    mb_param[index].get = get_log_entries_number;
    mb_param[index].check_handler = mb_check_dummy;
    
    index++;
    
    // Емкость архива (максимальная)
    mb_param[index].reg = 0x0902;
	mb_param[index].size = 1;
	mb_param[index].param = (uint8_t*)&archive_entries_capacity; // 
	mb_param[index].set = NULL;
    mb_param[index].get = NULL;
    mb_param[index].check_handler = mb_check_dummy;
    
    index++;
    
    // Текущее количество записей в архиве
    mb_param[index].reg = 0x0903;
	mb_param[index].size = 1;
	mb_param[index].param = NULL; // 
	mb_param[index].set = NULL;
    mb_param[index].get = get_archive_entries_number;
    mb_param[index].check_handler = mb_check_dummy;
    
    index++;
    
/*    
    // Емкость архива (максимальная)
    mb_param[index].reg = 0x0901;
	mb_param[index].size = 1;
	mb_param[index].param = (uint8_t*)&log_entries_capacity; // 
	mb_param[index].set = NULL;
    mb_param[index].get = NULL;
    mb_param[index].check_handler = mb_check_dummy;
    
    index++;
*/    
}


// Возвращает размер параметра в регистрах
bool mb_find_param(uint16_t reg, uint16_t *index, uint16_t *size)
{
	for (uint16_t i = 0; i < MB_PARAM_MAX; i++)
	{
		if (mb_param[i].reg == reg)
		{
			*index = i;
			*size = mb_param[i].size;
			return true;
		}
	}
	return false;
}


//
mb_delay_action_t mb_set_param(uint8_t *buf, uint16_t index)
{
	uint8_t *ptr = mb_param[index].param;

    // Если параметр только для чтения
    if (mb_param[index].check_handler == NULL)
        return MB_NO_ACTION;
    
	for (uint16_t i = 0; i < 2*mb_param[index].size; i++)
	{
		*ptr = buf[2*mb_param[index].size - 1 - i];
		ptr++;
	}
  
/*    
    if (mb_param[index].check_handler != NULL)
        mb_param[index].check_handler();
*/    
    
    mb_param[index].check_handler();
    
    if (mb_param[index].set != NULL)
        return mb_param[index].set();
    else
        return MB_NO_ACTION;
    
/*    
    if (mb_param[index].f_activity)
        return mb_param[index].set_handler();
    else
        return MB_NO_ACTION;
*/    
}


//
void mb_get_param(uint8_t *buf, uint16_t index)
{
    uint8_t *ptr;
	
    if (mb_param[index].get != NULL) {
        mb_param[index].get(buf, mb_param[index].size);
        return;
    }

    ptr = mb_param[index].param + 2*mb_param[index].size - 1;

	for (uint16_t i = 0; i < 2*mb_param[index].size; i++)
	{
		*buf = *ptr;
		buf++;
		ptr--;
	}
}





// -------------------------------------------------------------------------- //
//                          Чтение параметров
// -------------------------------------------------------------------------- //

void get_time(uint8_t* buf, uint8_t size)
{
    uint32_t rtc_unix = RTC_GetUnixTime();
    uint8_t *ptr = (uint8_t*)&rtc_unix + 2*size - 1;

    for (uint16_t i = 0; i < 2*size; i++)
	{
		*buf = *ptr;
		buf++;
		ptr--;
	}
}

//
void get_din_mode(uint8_t* buf, uint8_t size)
{
    
}

//
void get_log_entries_number(uint8_t* buf, uint8_t size)
{
    uint16_t capacity = log_capacity();
    SWAP_16(buf, capacity);
}

//
void get_archive_entries_number(uint8_t* buf, uint8_t size)
{
    uint16_t capacity = log_arch_capacity();
    SWAP_16(buf, capacity);
}


// -------------------------------------------------------------------------- //
//                          Установка параметров
// -------------------------------------------------------------------------- //

//
mb_delay_action_t mb_set_din_mode(void)
{
    in_set();
    return MB_NO_ACTION;
}

//
mb_delay_action_t mb_set_do(void)
{
    //do_set();
    do_set_common();
    return MB_NO_ACTION;
}

//
mb_delay_action_t mb_set_do_mode(void)
{
    do_set_mode();
    return MB_NO_ACTION;
}

//
mb_delay_action_t mb_set_time(void)
{
    TM_RTC_SetDataTimeUnix(rtc_sinhro);
    
    return MB_NO_ACTION;
}



// -------------------------------------------------------------------------- //
//                      Проверка параметров                                   //
// -------------------------------------------------------------------------- //

//
void mb_check_dummy(void)
{
}




