//
// Created by villuton on 26.08.2025.
//
#include "SerialPorts.h"
#include "at32f403a_407.h"

tSerialPorts SERIAL_PORTS;

///начало----------------------------------Командный интерфейс----------------------------------------------------------
///начало----------------------------------Командный интерфейс----------------------------------------------------------
///начало----------------------------------Командный интерфейс----------------------------------------------------------

///Буфер порта
uint8_t buf_USART1_DMA[1024];

/// IDLE прерывание
void USART1_IRQHandler() {
    // Смотрим idle прерывание
    if (usart_flag_get(SERIAL_PORTS.comint.uart, USART_IDLEF_FLAG)) {
        // Сброс прерывания
        usart_data_receive(SERIAL_PORTS.comint.uart);

        vSerialPortIrqProcessingDMAloop(&SERIAL_PORTS.comint, SERIAL_PORTS.comint.dma_init_struct.buffer_size -
                                                              SERIAL_PORTS.comint.dma_channel->dtcnt);

    }
}

/// RX
void DMA1_Channel3_IRQHandler(void) {
    if (dma_flag_get(DMA1_FDT3_FLAG)) {

        vSerialPortIrqProcessingDMAloop(&SERIAL_PORTS.comint,
                                        SERIAL_PORTS.comint.dma_init_struct.buffer_size);
        SERIAL_PORTS.comint.offset = 0;
        dma_flag_clear(DMA1_FDT3_FLAG);
    }
}

/// TX
void DMA1_Channel4_IRQHandler(void) {
    if (dma_flag_get(DMA1_FDT4_FLAG)) {
        dma_flag_clear(DMA1_FDT4_FLAG);
    }
}

/// Настройка порта
static void vSerialPort_InitUSART1(tSerialPortArtery *env) {
    gpio_init_type GPIO_InitStruct;

    gpio_default_para_init(&GPIO_InitStruct);

    GPIO_InitStruct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    GPIO_InitStruct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    GPIO_InitStruct.gpio_mode = GPIO_MODE_MUX;
    GPIO_InitStruct.gpio_pins = GPIO_PINS_9 | GPIO_PINS_10;
    GPIO_InitStruct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &GPIO_InitStruct);

    vSerialPortInitDMA(env,
                       USART1,
                       DMA1,
                       DMA1_CHANNEL3,
                       FLEX_CHANNEL3,
                       DMA_FLEXIBLE_UART1_RX,
                       buf_USART1_DMA,
                       sizeof(buf_USART1_DMA),
                       DMA1_Channel3_IRQn,
                       false,
                       115200,
                       USART1_IRQn,
                       CRM_USART1_PERIPH_CLOCK,
                       0x59,
                       1024,
                       0
    );


}

///конец-----------------------------------Командный интерфейс----------------------------------------------------------
///конец-----------------------------------Командный интерфейс----------------------------------------------------------
///конец-----------------------------------Командный интерфейс----------------------------------------------------------


/**
 * Инициализация серийного порта, RS485
 * @param *directionPins tRS485DirectionPins
 */
void SerialPorts_Init(tRS485DirectionPins *directionPins) {
    tSerialPorts *env = &SERIAL_PORTS;

    /// USART1 КОМАНДНЫЙ ИНТЕРФЕЙС
    vSerialPort_InitUSART1(&env->comint);
    SERIAL_PORTS.comint_IO = vSerialPortGetIo(&SERIAL_PORTS.comint);

    /// Полудуплекс RS485
    SERIAL_PORTS.comInt_HD = vSerialPortHalfDuplexInit(&SERIAL_PORTS.comint_IO,
                                                       &directionPins->reDePin,
                                                       &directionPins->reDePin);
    SERIAL_PORTS.comint_HD_IO = vSerialPortHalfDuplexGetIo(&SERIAL_PORTS.comInt_HD);

    /// TODO Удалить виртуальные порты, если не будет сервисной программы
    /// Виртуальные порты для сервисной программы (потенциально)
    SerialPortP2p_Init(&env->cliVirtualPort, 1 * 1024, 1024);
    env->cliVirtualInIo = SerialPortP2p_GetIoFirst(&env->cliVirtualPort);
    env->cliVirtualOutIo = SerialPortP2p_GetIoSecond(&env->cliVirtualPort);

}