#include "main.h"
#include "stm32f1xx_it.h"

#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"

#include "app_runtime.h"
#include "config.h"
#include "debug_log.h"
#include "uart_trans.h"

extern SPI_HandleTypeDef hspi1;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;
extern DMA_HandleTypeDef hdma_usart2_rx;
extern DMA_HandleTypeDef hdma_usart2_tx;
extern DMA_HandleTypeDef hdma_usart3_rx;
extern DMA_HandleTypeDef hdma_usart3_tx;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;

void NMI_Handler(void)
{
    while (1) {
    }
}

void HardFault_Handler(void)
{
    Debug_TrapWithRttHint("hardfault");
    while (1) {
    }
}

void MemManage_Handler(void)
{
    Debug_TrapWithRttHint("memmanage");
    while (1) {
    }
}

void BusFault_Handler(void)
{
    Debug_TrapWithRttHint("busfault");
    while (1) {
    }
}

void UsageFault_Handler(void)
{
    Debug_TrapWithRttHint("usagefault");
    while (1) {
    }
}

void DebugMon_Handler(void)
{
}

void SysTick_Handler(void)
{
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
        xPortSysTickHandler();
    }
}

void DMA1_Channel2_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma_usart3_tx);
}

void DMA1_Channel3_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma_usart3_rx);
}

void DMA1_Channel4_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma_usart1_tx);
}

void DMA1_Channel5_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma_usart1_rx);
}

void DMA1_Channel6_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma_usart2_rx);
}

void DMA1_Channel7_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma_usart2_tx);
}

void EXTI0_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET) {
        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
        if ((xNetSemaphore != NULL) &&
            (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)) {
            xSemaphoreGiveFromISR(xNetSemaphore, &xHigherPriorityTaskWoken);
            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
        }
    }
}

void SPI1_IRQHandler(void)
{
    HAL_SPI_IRQHandler(&hspi1);
}

void USART1_IRQHandler(void)
{
    if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET) {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);
        config_uart_idle_handler();
    }
    HAL_UART_IRQHandler(&huart1);
}

void USART2_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET) {
        __HAL_UART_CLEAR_IDLEFLAG(&huart2);
        uart_trans_notify_rx_from_isr(UART_CHANNEL_U0, &xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    }
    HAL_UART_IRQHandler(&huart2);
}

void USART3_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE) != RESET) {
        __HAL_UART_CLEAR_IDLEFLAG(&huart3);
        uart_trans_notify_rx_from_isr(UART_CHANNEL_U1, &xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    }
    HAL_UART_IRQHandler(&huart3);
}

void TIM4_IRQHandler(void)
{
    if ((TIM4->SR & TIM_SR_UIF) != 0u) {
        TIM4->SR &= ~TIM_SR_UIF;
    }
    HAL_IncTick();
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart == &huart2) {
        uart_trans_tx_cplt_handler(UART_CHANNEL_U0);
    } else if (huart == &huart3) {
        uart_trans_tx_cplt_handler(UART_CHANNEL_U1);
    }
}
