#include "Bsp.h"

#ifdef USE_DIGITAL_OUTPUT
GPIO_LIST GpioOutputList[] = 
{
    {GPIOA,GPIO_Pin_0},
};
#endif

#ifdef USE_DIGITAL_INPUT
GPIO_LIST GpioInputList[] = 
{
    {GPIOA,GPIO_Pin_0},
};
#endif

#ifdef USE_LED
GPIO_LIST GpioLedList[] = 
{
    {GPIOB,GPIO_Pin_5},
    {GPIOE,GPIO_Pin_5},
};
#endif

/**
 * @brief  BSP的配置和初始化
 * @param  void
 * @retval void
 * @note   void
 * @example void
 */
void BspConfigInit(void)
{
    //Interrupt
    IntCbInit();

    //Delay
    DelayConfig();

    //SystemClock
    {
        #ifdef GPIO_ENABLE
        BspInitGpioClock();
        #endif
        #ifdef USART_ENABLE
        BspInitUsartClock();
        #endif
    }

    //GPIO DO DI
    {
        //DO
        #ifdef USE_DIGITAL_OUTPUT
        for (uint8_t i = 0; i < DO_NUM; i++) {
            GpioConfig(GpioOutputList[i].GpioX,GpioOutputList[i].GpioPinX,GPIO_Mode_Out_PP,GPIO_Speed_50MHz);
            SetGpioSts(GpioOutputList[i].GpioX,GpioOutputList[i].GpioPinX,false);
        }
        #endif
        //DI
        #ifdef USE_DIGITAL_INPUT
        for (uint8_t i = 0; i < DI_NUM; i++) {
            GpioConfig(GpioInputList[i].GpioX,GpioInputList[i].GpioPinX,GPIO_Mode_IPU,GPIO_Speed_50MHz);
            SetGpioSts(GpioInputList[i].GpioX,GpioInputList[i].GpioPinX,false);
        }
        #endif
        //LED
        #ifdef USE_LED
        for (uint8_t i = 0; i < LED_NUM; i++) {
            GpioConfig(GpioLedList[i].GpioX,GpioLedList[i].GpioPinX,GPIO_Mode_Out_PP,GPIO_Speed_50MHz);
            SetGpioSts(GpioLedList[i].GpioX,GpioLedList[i].GpioPinX,(bool_t)SET);
        }
        #endif
    }

    //USART
    {
        //串口的TX引脚需要复用推挽模式，RX引脚需要浮空输入模式
        #ifdef USE_USART1
        GpioConfig(COM0_TX_PORT,COM0_TX_PIN,GPIO_Mode_AF_PP,GPIO_Speed_50MHz);
        GpioConfig(COM0_RX_PORT,COM0_RX_PIN,GPIO_Mode_IN_FLOATING,GPIO_Speed_50MHz);
        #endif
        #ifdef USE_USART2
        GpioConfig(COM1_TX_PORT,COM1_TX_PIN,GPIO_Mode_AF_PP,GPIO_Speed_50MHz);
        GpioConfig(COM1_RX_PORT,COM1_RX_PIN,GPIO_Mode_AF_PP,GPIO_Speed_50MHz);
        #endif
        #ifdef USE_USART3
        GpioConfig(COM2_TX_PORT,COM2_TX_PIN,GPIO_Mode_AF_PP,GPIO_Speed_50MHz);
        GpioConfig(COM2_RX_PORT,COM2_RX_PIN,GPIO_Mode_AF_PP,GPIO_Speed_50MHz);
        #endif
        #ifdef USE_USART4
        GpioConfig(COM3_TX_PORT,COM3_TX_PIN,GPIO_Mode_AF_PP,GPIO_Speed_50MHz);
        GpioConfig(COM3_RX_PORT,COM3_RX_PIN,GPIO_Mode_AF_PP,GPIO_Speed_50MHz);
        #endif
        #ifdef USE_USART5
        GpioConfig(COM4_TX_PORT,COM4_TX_PIN,GPIO_Mode_AF_PP,GPIO_Speed_50MHz);
        GpioConfig(COM4_RX_PORT,COM4_RX_PIN,GPIO_Mode_AF_PP,GPIO_Speed_50MHz);
        #endif
    }
}

//用户层接口
/**
 * @brief  IO控制
 * @param  void
 * @retval void
 * @note   void
 * @example void
 */
uint32_t IoCtl(uint8_t IoType, uint16_t IoChnl,uint32_t state)
{
    switch (IoType) {
        #ifdef USE_DIGITAL_OUTPUT
        case IO_TYPE_DO:
            SetGpioSts(GpioOutputList[IoChnl].GpioX,GpioOutputList[IoChnl].GpioPinX,state);
            return 0;
        #endif
        #ifdef USE_DIGITAL_INPUT
        case IO_TYPE_DI:
            return GetGpioSts(GpioInputList[IoChnl].GpioX,GpioInputList[IoChnl].GpioPinX);
        #endif
        #ifdef USE_ANALOG_OUTPUT
        case IO_TYPE_AO:
            break;
        #endif
        #ifdef USE_ANALOG_INPUT
        case IO_TYPE_AI:
            break;
        #endif
        #ifdef  USE_LED
        case IO_TYPE_LED:
            SetGpioSts(GpioLedList[IoChnl].GpioX,GpioLedList[IoChnl].GpioPinX,(bool_t)state);
            return 0;
        #endif
        default:
            return 0;
    }

    return 0;
}

/**
 * @brief  反转DO口
 * @param  void
 * @retval void
 * @note   void
 * @example void
 */
void IoCtlToggleDo(uint16_t IoChnl)
{
    #ifdef USE_DIGITAL_OUTPUT
    if (GetGpioSts(GpioOutputList[IoChnl].GpioX, GpioOutputList[IoChnl].GpioPinX) == 0)
    {
        SetGpioSts(GpioOutputList[IoChnl].GpioX,GpioOutputList[IoChnl].GpioPinX,1);
    }
    else
    {
       SetGpioSts(GpioOutputList[IoChnl].GpioX,GpioOutputList[IoChnl].GpioPinX,0); 
    }
    #endif
}

/**
 * @brief  反转LED口
 * @param  void
 * @retval void
 * @note   void
 * @example void
 */
void IoCtlLedToggle(uint16_t IoChnl)
{
    #ifdef USE_LED
    if (GetGpioSts(GpioLedList[IoChnl].GpioX, GpioLedList[IoChnl].GpioPinX) == 0)
    {
        SetGpioSts(GpioLedList[IoChnl].GpioX,GpioLedList[IoChnl].GpioPinX,true);
    }
    else
    {
       SetGpioSts(GpioLedList[IoChnl].GpioX,GpioLedList[IoChnl].GpioPinX,false); 
    }
    #endif
}

/**
* @brief 重写Printf函数
* @param
* @retval void
* @note   void
* @example void
*/
#if defined (__GNUC__) || defined (__SEGGER__)
    #include <SysCall.c>
#elif defined(__CC_ARM) || defined(__CLANG_ARM)
int fputc(int ch, FILE *f)
{
    UsartSendChar(TTY_COM, ch);
    return ch;
}
int fgetc(FILE *f)
{
    uint8_t ch;
    ch = UsartReceiveChar(TTY_COM);
    return ch;
}
#endif
