#include "Bsp.h"

#ifdef TTY_COM
#include "LetterShell.h"
#endif

// LED灯数组
#if (LED_NUM != 0)
const GPIO_CONFIG LED_PERIPH[] = {
    {.GpioX = GPIO21, .Mode = GPIO_Mode_Out_PP, .Speed = GPIO_Speed_10MHz},
    {.GpioX = GPIO69, .Mode = GPIO_Mode_Out_PP, .Speed = GPIO_Speed_10MHz},
};
#endif
//数字输入数组
#if (DI_NUM != 0)
const GPIO_CONFIG DI_PERIPH[] = {
    {},
};
#endif
//数字输出数组
#if (DO_NUM != 0)
const GPIO_CONFIG DO_PERIPH[] = {
    {},
};
#endif
//串口配置表
const COM_CONFIG COM_PERIPH[] = {
    {COM0,.TxPort = GPIO9, .RxPort =GPIO10},
    {COM1,.TxPort = GPIO2, .RxPort = GPIO3,.TxRxEn = GPIO55},
};

void BspExtraInit(void);

/**
 * @brief  Voilet BSP的初始化函数
 * @note  void
 * @param void
 * @retval void
 */
void BspInit(void) {
    unsigned char i = 0;

    INTERRUPT_DISABLE

    //初始化中断系统
    IrqInit();

    //初始化延时库
    DelayConfig();

    //LED灯配置
#if (LED_NUM != 0)
    for (i = 0;i < ARRAY_LEN(LED_PERIPH);i++) {
        //配置GPIO口
        GpioConfig(&LED_PERIPH[i].GpioX, LED_PERIPH[i].Mode, LED_PERIPH[i].Speed);
    }
#endif

    //DI采集配置
#if (DI_NUM != 0)
    // for (i = 0;i < DI_NUM;i++) {
    //     //打开外设时钟
    //     GpioClockEnable(&LED_PERIPH[i].GpioX);
    //     //配置GPIO口
    //     GpioConfig(&LED_PERIPH[i].GpioX, LED_PERIPH[i].Mode, LED_PERIPH[i].Speed);
    // }
#endif

    //DO输出配置
#if (DO_NUM != 0)
    // for (i = 0;i < DO_NUM;i++) {
    //     //打开外设时钟
    //     GpioClockEnable(&LED_PERIPH[i].GpioX);
    //     //配置GPIO口
    //     GpioConfig(&LED_PERIPH[i].GpioX, LED_PERIPH[i].Mode, LED_PERIPH[i].Speed);
    // }
#endif

    //串口配置
    for (i = 0;i < ARRAY_LEN(COM_PERIPH);i++) {
        GpioConfig(&COM_PERIPH[i].TxPort, GPIO_Mode_AF_PP, GPIO_Speed_2MHz);
        GpioConfig(&COM_PERIPH[i].RxPort, GPIO_Mode_IPU, GPIO_Speed_2MHz);
    }

    INTERRUPT_ENABLE

    BspExtraInit();
}

/**
 * @brief  扩展库初始化
 * @note  理论上扩展库要在BSP的最后加载
 * @param  void
 * @retval void
 */
void BspExtraInit(void)
{
    //LetterShell初始化
#ifdef TTY_COM
    LetterShellInit(TTY_COM,TTY_BAUD);
#endif
}

/**
 * @brief  打开LED灯
 * @note   void
 * @param  Chnl 通道
 * @retval void
 */
void LedOn(uint8_t Chnl)
{
    if (Chnl >= LED_NUM)
        return;
    GpioSet(&LED_PERIPH[Chnl].GpioX, RESET);
}
/**
 * @brief  关闭LED灯
 * @note   void
 * @param  Chnl 通道
 * @retval void
 */
void LedOff(uint8_t Chnl)
{
    if (Chnl >= LED_NUM)
        return;
    GpioSet(&LED_PERIPH[Chnl].GpioX, SET);
}

void LedSet(uint8_t Chnl,uint8_t Value)
{
    if (Chnl >= LED_NUM)
        return;
    if (Value == LED_ON) {
        GpioSet(&LED_PERIPH[Chnl].GpioX, RESET);
    }
    else {
        GpioSet(&LED_PERIPH[Chnl].GpioX, SET);
    }
}

/**
 * @brief  切换LED灯状态
 * @note   void
 * @param  Chnl 通道 Status 状态
 * @retval void
 */
void LedToggle(uint8_t Chnl)
{
    if (Chnl >= LED_NUM)
        return;
    if (GpioGet(&LED_PERIPH[Chnl].GpioX) == LED_ON)
    {
        GpioSet(&LED_PERIPH[Chnl].GpioX,LED_OFF);
    }
    else
    {
        GpioSet(&LED_PERIPH[Chnl].GpioX,LED_ON);
    }
}

void Rs485StdConfig(const COM_MAP_T *ComX,unsigned int Baud)
{
    for (unsigned char i = 0;i < ARRAY_LEN(COM_PERIPH);i++) {
        if (ComX == COM_PERIPH[i].ComX) {
            if (COM_PERIPH[i].TxRxEn.ClockTree) {
                GpioSet(&COM_PERIPH[i].TxRxEn,Baud);
            }
            ComStdConfig(COM_PERIPH[i].ComX,Baud);
        }
    }
}

void Rs485AdvConfig(const COM_MAP_T *ComX, uint32_t Baud, uint8_t DataBits, uint8_t StopBits, uint8_t Parity)
{

}

/**
* @brief 重写Printf函数
* @note void
* @param void
* @retval void
*/
#if 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
