#include "misc.h"
#include "FreeRTOS.h"
#include "task.h"
#include "mux.h"
#include "mb.h"
#include "mbport.h"
#include "at32f403a_407_board.h"
#include <stdio.h>

char recv_buf[1024] = {0};

// TIM1, 8, 9, 10, 11 тактируются от 120 МГц
// TIM2, 3, 4, 5, 6, 7, 12, 13, 14 тактируются от 240 МГц

void nop(uint32_t cnt);



void modbus_tim_init(void)
{
    crm_clocks_freq_type crm_clocks_freq_struct = {0};
    
    crm_periph_clock_enable(CRM_TMR7_PERIPH_CLOCK, TRUE);

    crm_clocks_freq_get(&crm_clocks_freq_struct);
    tmr_base_init(TMR7, 1, 5999);
    tmr_cnt_dir_set(TMR7, TMR_COUNT_UP);
        
    tmr_flag_clear(TMR7, TMR_OVF_FLAG);

    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
    nvic_irq_enable(TMR7_GLOBAL_IRQn, 5, 0);
       
    tmr_counter_enable(TMR7, TRUE);
    
    tmr_interrupt_enable(TMR7, TMR_OVF_INT, TRUE);
}

//
void modbus_init(void)
{
    const UCHAR ucSlaveID[] = {0xAA, 0xBB, 0xCC};
    uint32_t baud = 115200;
    eMBParity par = MB_PAR_NONE;
    UCHAR mb_addr = 1;
    unsigned int stop_bits = 1;
#if 1    
    eMBInit(MB_RTU, mb_addr, 4, baud, par, stop_bits);
    eMBSetSlaveID(0x34, TRUE, ucSlaveID, 3);
	eMBEnable();
#endif    
}

//
void test_modbus_port_init(void)
{
    gpio_init_type gpio_init_struct;

    crm_periph_clock_enable(CRM_USART3_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
    gpio_pin_remap_config(USART3_GMUX_0011, TRUE);
    
    gpio_default_para_init(&gpio_init_struct);

    // configure the uart tx pin
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_pins = GPIO_PINS_8;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOD, &gpio_init_struct);

    // configure the uart rx pin
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_9;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOD, &gpio_init_struct);
    
    // configure the uart rx pin
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_10;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOD, &gpio_init_struct);
    
    MB_RX_ENABLE;
    
    // configure uart param
    usart_init(USART3, 115200, USART_DATA_8BITS, USART_STOP_1_BIT);
    usart_parity_selection_config(USART3, USART_PARITY_NONE);
    
    usart_flag_clear(USART3, USART_RDBF_FLAG);
    usart_interrupt_enable(USART3, USART_RDBF_INT, TRUE);
    usart_receiver_enable(USART3, TRUE);
    usart_transmitter_enable(USART3, TRUE);
    usart_enable(USART3, TRUE);  
    
    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
    nvic_irq_enable(USART3_IRQn, 5, 0);
}


void nop(uint32_t cnt)
{
    for (uint32_t i = 0; i < cnt; i++)
        __NOP();
}



// PA_2 (pin_25)
void mb_test_gpio_init(void)
{
    gpio_init_type gpio_init_struct;
    
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
    
    gpio_default_para_init(&gpio_init_struct);

    // configure the uart tx pin
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_2;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &gpio_init_struct);
    
    
}

//
void pwm_test(void)
{
    tmr_output_config_type tmr_oc_init_structure;
    
    pwm_gpio_config();
    
    uint16_t prescaler_value = 0;
    uint16_t pulse = 0;
    uint16_t timer_period = 10000 - 1;

    // Режим PWM
    crm_periph_clock_enable(CRM_TMR9_PERIPH_CLOCK, TRUE);
    
    prescaler_value = (uint16_t)(system_core_clock / 10000) - 1;
    tmr_base_init(TMR9, timer_period, prescaler_value);
    pulse = (uint16_t)(((uint32_t) 70 * (timer_period - 1)) / 100);   // 70%
    
    tmr_cnt_dir_set(TMR9, TMR_COUNT_UP);
    tmr_clock_source_div_set(TMR9, TMR_CLOCK_DIV1);
    
    tmr_output_default_para_init(&tmr_oc_init_structure);
    tmr_oc_init_structure.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
    tmr_oc_init_structure.oc_idle_state = FALSE;
    tmr_oc_init_structure.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
    tmr_oc_init_structure.oc_output_state = TRUE;
    tmr_output_channel_config(TMR9, TMR_SELECT_CHANNEL_2, &tmr_oc_init_structure);
    tmr_channel_value_set(TMR9, TMR_SELECT_CHANNEL_2, pulse);
    tmr_output_channel_buffer_enable(TMR9, TMR_SELECT_CHANNEL_2, TRUE);
    
    tmr_period_buffer_enable(TMR12, TRUE);
    
    nvic_irq_enable(TMR1_BRK_TMR9_IRQn, 5, 0);

    tmr_interrupt_enable(TMR9, TMR_C2_INT, TRUE);
    
    tmr_counter_enable(TMR9, TRUE);
}

//
void pwm_gpio_config(void)
{
    gpio_init_type gpio_init_struct;

    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
    
    gpio_default_para_init(&gpio_init_struct);
    
#if 0    
    // Пин в режиме PWM таймера
    gpio_init_struct.gpio_pins = GPIO_PINS_15;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(GPIOB, &gpio_init_struct);
#endif    
    
    gpio_init_struct.gpio_pins = GPIO_PINS_15;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(GPIOB, &gpio_init_struct);
    
    // Простой выход
    gpio_init_struct.gpio_pins = GPIO_PINS_13;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(GPIOB, &gpio_init_struct);
}


#if 0
// Для отладки PWM режимов TMR_12
void TMR8_BRK_TMR12_IRQHandler(void)
{
    if(tmr_flag_get(TMR12, TMR_C2_FLAG) != RESET)
    {
        tmr_flag_clear(TMR12, TMR_C2_FLAG);

        GPIOB->odt ^= GPIO_PINS_13;
    }
}
#endif

    
#if 0
void USART3_IRQHandler(void)
{
    char rx_byte;
    static int counter = 0;
    
    if (usart_flag_get(USART3, USART_RDBF_FLAG) != RESET) {
        rx_byte = USART3->dt;
        PRINT_UART->dt = ((uint16_t)rx_byte & 0x01FF); 
        recv_buf[counter++] = rx_byte;
  
        if (counter == 1024)
            counter = 0;
        
        MB_TX_ENABLE;
        nop(10000);
        while(usart_flag_get(USART3, USART_TDBE_FLAG) == RESET);
        USART3->dt = ((uint16_t)(rx_byte + 1) & 0x01FF);
        while(usart_flag_get(USART3, USART_TDC_FLAG) == RESET);
        MB_RX_ENABLE;
        
    }  
}      
#endif

#if 0
//
void TMR7_GLOBAL_IRQHandler(void)
{
    if(tmr_flag_get(TMR7, TMR_OVF_FLAG) != RESET)
    {
        tmr_flag_clear(TMR7, TMR_OVF_FLAG);
        mux_led_test_toggle();
    }
}
#endif