/**
 ******************************************************************************
 * @file    main.c
 * @author  MCU Application Team
 * @brief   Main program body
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; Copyright (c) Puya Semiconductor Co.
 * All rights reserved.</center></h2>
 *
 * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
 * All rights reserved.</center></h2>
 *
 * This software component is licensed by ST under BSD 3-Clause license,
 * the "License"; You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                        opensource.org/licenses/BSD-3-Clause
 *
 ******************************************************************************
 */
/* Includes ------------------------------------------------------------------*/
#include "led_drivers.h"
#if APP_LED_ENABLE
static uint8_t led_run;
static uint8_t led_offset;
static uint32_t LED_PORTA;
static uint32_t LED_PORTB;
static uint32_t LED_PORTF;
uint8_t led_data[LED_COUNT - 1];
#if (TK_LED_MATRIIX == 0)//4X4
    #define X_END             3
    #define Y_END             3
	#if LED_COUNT < 5
	#error "error! 点阵设置错误"
	#endif
#elif (TK_LED_MATRIIX == 1)//5X5
    #define X_END             4
    #define Y_END             4
	#if LED_COUNT < 6
	#error "error! 点阵设置错误"
	#endif
#elif (TK_LED_MATRIIX == 2)//6X6
    #define X_END             5
    #define Y_END             5
	#if LED_COUNT < 7
	#error "error! 点阵设置错误"
	#endif
#elif (TK_LED_MATRIIX == 3)//6X7
    #define X_END             6
    #define Y_END             5
	#if LED_COUNT < 7
	#error "error! 点阵设置错误"
	#endif
#elif (TK_LED_MATRIIX == 4)//7X7
    #define X_END             6
    #define Y_END             6
	#if LED_COUNT < 8
	#error "error! 点阵设置错误"
	#endif
#else                       //7X8
    #define X_END             7
    #define Y_END             6
	#if LED_COUNT < 8
	#error "error! 点阵设置错误"
	#endif
#endif
/**
 * @brief 数码管IO
 */
const uint8_t LED_TBL[8] = {    LED0_GPIO_PIN, LED1_GPIO_PIN, LED2_GPIO_PIN, LED3_GPIO_PIN,
                                LED4_GPIO_PIN, LED5_GPIO_PIN, LED6_GPIO_PIN, LED7_GPIO_PIN
                           };

/*      H               L   */
const uint8_t SEG_TBL[56][2] =
{
    {LED0_GPIO_PIN, LED1_GPIO_PIN}, //0       //前面输出高，后面输出低则点亮这个位置
    {LED1_GPIO_PIN, LED0_GPIO_PIN}, //1
    {LED2_GPIO_PIN, LED0_GPIO_PIN}, //2
    {LED3_GPIO_PIN, LED0_GPIO_PIN}, //3
    {LED4_GPIO_PIN, LED0_GPIO_PIN}, //4
    {LED5_GPIO_PIN, LED0_GPIO_PIN}, //5
    {LED6_GPIO_PIN, LED0_GPIO_PIN}, //6
    {LED7_GPIO_PIN, LED0_GPIO_PIN}, //7

    {LED0_GPIO_PIN, LED2_GPIO_PIN}, //8       //前面输出高，后面输出低则点亮这个位置
    {LED1_GPIO_PIN, LED2_GPIO_PIN}, //9
    {LED2_GPIO_PIN, LED1_GPIO_PIN}, //10
    {LED3_GPIO_PIN, LED1_GPIO_PIN}, //11
    {LED4_GPIO_PIN, LED1_GPIO_PIN}, //12
    {LED5_GPIO_PIN, LED1_GPIO_PIN}, //13
    {LED6_GPIO_PIN, LED1_GPIO_PIN}, //14
    {LED7_GPIO_PIN, LED1_GPIO_PIN}, //15

    {LED0_GPIO_PIN, LED3_GPIO_PIN}, //16      //前面输出高，后面输出低则点亮这个位置
    {LED1_GPIO_PIN, LED3_GPIO_PIN}, //17
    {LED2_GPIO_PIN, LED3_GPIO_PIN}, //18
    {LED3_GPIO_PIN, LED2_GPIO_PIN}, //19
    {LED4_GPIO_PIN, LED2_GPIO_PIN}, //20
    {LED5_GPIO_PIN, LED2_GPIO_PIN}, //21
    {LED6_GPIO_PIN, LED2_GPIO_PIN}, //22
    {LED7_GPIO_PIN, LED2_GPIO_PIN}, //23

    {LED0_GPIO_PIN, LED4_GPIO_PIN}, //24      //前面输出高，后面输出低则点亮这个位置
    {LED1_GPIO_PIN, LED4_GPIO_PIN}, //25
    {LED2_GPIO_PIN, LED4_GPIO_PIN}, //26
    {LED3_GPIO_PIN, LED4_GPIO_PIN}, //27
    {LED4_GPIO_PIN, LED3_GPIO_PIN}, //28
    {LED5_GPIO_PIN, LED3_GPIO_PIN}, //29
    {LED6_GPIO_PIN, LED3_GPIO_PIN}, //30
    {LED7_GPIO_PIN, LED3_GPIO_PIN}, //31

    {LED0_GPIO_PIN, LED5_GPIO_PIN}, //32      //前面输出高，后面输出低则点亮这个位置
    {LED1_GPIO_PIN, LED5_GPIO_PIN}, //33
    {LED2_GPIO_PIN, LED5_GPIO_PIN}, //34
    {LED3_GPIO_PIN, LED5_GPIO_PIN}, //35
    {LED4_GPIO_PIN, LED5_GPIO_PIN}, //36
    {LED5_GPIO_PIN, LED4_GPIO_PIN}, //37
    {LED6_GPIO_PIN, LED4_GPIO_PIN}, //38
    {LED7_GPIO_PIN, LED4_GPIO_PIN}, //39

    {LED0_GPIO_PIN, LED6_GPIO_PIN}, //40      //前面输出高，后面输出低则点亮这个位置
    {LED1_GPIO_PIN, LED6_GPIO_PIN}, //41
    {LED2_GPIO_PIN, LED6_GPIO_PIN}, //42
    {LED3_GPIO_PIN, LED6_GPIO_PIN}, //43
    {LED4_GPIO_PIN, LED6_GPIO_PIN}, //44
    {LED5_GPIO_PIN, LED6_GPIO_PIN}, //45
    {LED6_GPIO_PIN, LED5_GPIO_PIN}, //46
    {LED7_GPIO_PIN, LED5_GPIO_PIN}, //47

    {LED0_GPIO_PIN, LED7_GPIO_PIN}, //48      //前面输出高，后面输出低则点亮这个位置
    {LED1_GPIO_PIN, LED7_GPIO_PIN}, //49
    {LED2_GPIO_PIN, LED7_GPIO_PIN}, //50
    {LED3_GPIO_PIN, LED7_GPIO_PIN}, //51
    {LED4_GPIO_PIN, LED7_GPIO_PIN}, //52
    {LED5_GPIO_PIN, LED7_GPIO_PIN}, //53
    {LED6_GPIO_PIN, LED7_GPIO_PIN}, //54
    {LED7_GPIO_PIN, LED6_GPIO_PIN}, //55
};
#if (TK_LED_NUM == 2)
const uint8_t LED_BANK[32][2] =
{
    {0, 0XFF}, //0
    {1, 2}, //1
    {3, 4}, //2
    {5, 6}, //3
    {7, 0XFF}, //4
    {8, 9}, //5
    {10, 11}, //6
    {12, 13}, //7
    {14, 15}, //8
    {16, 17}, //9
    {18, 0XFF}, //10
    {19, 20}, //11
    {21, 22}, //12
    {23, 0XFF}, //13
    {24, 25}, //14
    {26, 27}, //15
    {28, 29}, //16
    {30, 31}, //17
    {32, 33}, //18
    {34, 35}, //19
    {36, 0XFF}, //20
    {37, 38}, //21
    {39, 0XFF}, //22
    {40, 41}, //23
    {42, 43}, //24
    {44, 45}, //25
    {46, 47}, //26
    {48, 49}, //27
    {50, 51}, //28
    {52, 53}, //29
    {54, 0XFF}, //30
    {55, 0XFF}, //31
};
#elif (TK_LED_NUM == 3)
const uint8_t LED_BANK[32][3] =
{
    {0, 0XFF, 0XFF}, //0
    {1, 2, 3}, //1
    {4, 5, 6}, //2
    {7, 0XFF, 0XFF}, //3

    {8, 9, 0XFF}, //4
    {10, 11, 12}, //5
    {13, 14, 15}, //6

    {16, 17, 18}, //7
    {19, 20, 21}, //8
    {22, 23, 0XFF}, //9

    {24, 25, 0XFF}, //10
    {26, 27, 0XFF}, //11
    {28, 29, 0XFF}, //12
    {30, 31, 0XFF}, //13

    {32, 33, 34}, //14
    {35, 36, 0XFF}, //15
    {37, 38, 39}, //16

    {40, 41, 42}, //17
    {43, 44, 45}, //18
    {46, 47, 0XFF}, //19

    {48, 49, 50}, //20
    {51, 52, 53}, //21
    {54, 0XFF, 0XFF}, //22
    {55, 0XFF, 0XFF}, //23

    {56, 57, 58}, //24
    {59, 60, 61}, //25
    {62, 63, 0XFF}, //26
};
#endif
/********************************************************
**  函数名  void LED_Init(void)
**  描述    LED IO口初始化，
**  传入    ：无
**  返回    ：无
*********************************************************/
void LED_Init(void)
{
    uint8_t i;
    GPIO_TypeDef *GPIOx;
    uint32_t PINx;
    LED_PORTA = 0;
    LED_PORTB = 0;
    LED_PORTF = 0;
    for (i = 0; i < LED_COUNT; i++)
    {
        GPIO_Init(LED_TBL[i], OUTPUT | OPENDRAIN);
        GPIO_ClearBit(LED_TBL[i]);
        GPIOx = GPIO_PORT(LED_TBL[i]);
        PINx = GPIO_PIN(LED_TBL[i]);
        LL_GPIO_SetPinSpeed(GPIOx, PINx, LL_GPIO_SPEED_FREQ_VERY_HIGH);
        /*  用于控制所有LED IO状态  */
        if (GPIOx == GPIOA)
            LED_PORTA |= PINx;
        else if (GPIOx == GPIOB)
            LED_PORTB |= PINx;
        else if (GPIOx == GPIOF)
            LED_PORTF |= PINx;
    }
    LED_Default();
    led_run = 1;
}
/********************************************************
**  函数名  void LED_Sleep(void)
**  描述    数码管休眠，设置IO口状态
**  传入    ：无
**  返回    ：无
*********************************************************/
void LED_Sleep(void)
{
    led_run = 0;
    /*  所有LED开漏输出1，IO状态呈高阻态    */
    LL_GPIO_SetPinOutputType(GPIOA, LED_PORTA, LL_GPIO_OUTPUT_OPENDRAIN);
    LL_GPIO_SetPinOutputType(GPIOB, LED_PORTB, LL_GPIO_OUTPUT_OPENDRAIN);
    LL_GPIO_SetPinOutputType(GPIOF, LED_PORTF, LL_GPIO_OUTPUT_OPENDRAIN);
    GPIOA->ODR |= LED_PORTA;
    GPIOB->ODR |= LED_PORTB;
    GPIOF->ODR |= LED_PORTF;
}
/********************************************************
**  函数名  void LED_Wake(void)
**  描述    LED退出休眠，继续显示
**  传入    ：无
**  返回    ：无
*********************************************************/
void LED_Wake(void)
{
    led_run = 1;
}
/********************************************************
**  函数名  void LED_Scan(void)
**  描述    LED扫描
**  传入    ：无
**  返回    ：无
*********************************************************/
void LED_Scan(void)
{
#if (TK_LED_ENABLE == 0)
    if (led_run == 0)
        return;
    GPIO_TypeDef *GPIOxH, *GPIOxL;
    uint32_t PINxH, PINxL;
#if (TK_LED_NUM == 2)
    uint8_t seg1, seg2, com;
#elif (TK_LED_NUM == 3)
    uint8_t seg1, seg2, seg3, com;
#else
    uint8_t seg1, com;
#endif
    uint8_t out = 0;
    uint8_t led_seg;
    uint8_t led_com;
    /*  所有LED开漏输出1，IO状态呈高阻态    */
    LL_GPIO_SetPinOutputType(GPIOA, LED_PORTA, LL_GPIO_OUTPUT_OPENDRAIN);
    LL_GPIO_SetPinOutputType(GPIOB, LED_PORTB, LL_GPIO_OUTPUT_OPENDRAIN);
    LL_GPIO_SetPinOutputType(GPIOF, LED_PORTF, LL_GPIO_OUTPUT_OPENDRAIN);
    GPIOA->ODR |= LED_PORTA;
    GPIOB->ODR |= LED_PORTB;
    GPIOF->ODR |= LED_PORTF;
    /*  */
    do
    {
#if (TK_LED_NUM == 1)
        if (++led_offset > 55)
            led_offset = 0;
#elif (TK_LED_NUM == 2)
        if (++led_offset > 31)
            led_offset = 0;
#elif (TK_LED_NUM == 3)
        if (++led_offset > 26)
            led_offset = 0;
#endif
#if (TK_LED_NUM == 1)
        seg1 = led_offset;
        com = led_offset;
#else
        seg1 = LED_BANK[led_offset][0];
        seg2 = LED_BANK[led_offset][1];
#if (TK_LED_NUM == 3)
        seg3 = LED_BANK[led_offset][2];
#endif
        com = LED_BANK[led_offset][0];
#endif
        led_com = seg1 >> 3;
        led_seg = seg1 % 8;
    }
    while (led_seg > X_END || led_com > Y_END);
    /*  点亮对应的LED   */
    if (led_data[led_com] & (1 << led_seg))
    {
        GPIOxH = GPIO_PORT(SEG_TBL[seg1][0]);
        PINxH = GPIO_PIN(SEG_TBL[seg1][0]);
        LL_GPIO_SetPinOutputType(GPIOxH, PINxH, LL_GPIO_OUTPUT_PUSHPULL);
        out = 0X01;
    }
#if (TK_LED_NUM > 1)
    if (seg2 != 0XFF)
    {
        led_com = seg2 >> 3;
        led_seg = seg2 % 8;
        if (led_data[led_com] & (1 << led_seg))
        {
            GPIOxH = GPIO_PORT(SEG_TBL[seg2][0]);
            PINxH = GPIO_PIN(SEG_TBL[seg2][0]);
            LL_GPIO_SetPinOutputType(GPIOxH, PINxH, LL_GPIO_OUTPUT_PUSHPULL);
            out = 0X01;
        }
    }
#endif
#if (TK_LED_NUM > 2)
    if (seg3 != 0XFF)
    {
        led_com = seg3 >> 3;
        led_seg = seg3 % 8;
        if (led_data[led_com] & (1 << led_seg))
        {
            GPIOxH = GPIO_PORT(SEG_TBL[seg3][0]);
            PINxH = GPIO_PIN(SEG_TBL[seg3][0]);
            LL_GPIO_SetPinOutputType(GPIOxH, PINxH, LL_GPIO_OUTPUT_PUSHPULL);
            out = 0X01;
        }
    }
#endif
    /*  当前IO口输出0   */
    if (out)
    {
        GPIOxL = GPIO_PORT(SEG_TBL[com][1]);
        PINxL = GPIO_PIN(SEG_TBL[com][1]);
        GPIOxL->BRR = PINxL;
    }
#endif
}
#if (TK_LED_ENABLE == 1)
void TK_LED_Scan(uint8_t State)
{
    if (led_run == 0)
        return;
    GPIO_TypeDef *GPIOxH, *GPIOxL;
    uint32_t PINxH, PINxL;
#if (TK_LED_NUM == 2)
    uint8_t seg1, seg2, com;
#elif (TK_LED_NUM == 3)
    uint8_t seg1, seg2, seg3, com;
#else
    uint8_t seg1, com;
#endif
    uint8_t out = 0;
    uint8_t led_seg;
    uint8_t led_com;
    switch (State)
    {
    /*  关闭LED显示 */
    case TK_LED_OFF:
        /*  所有LED开漏输出1，IO状态呈高阻态    */
        LL_GPIO_SetPinOutputType(GPIOA, LED_PORTA, LL_GPIO_OUTPUT_OPENDRAIN);
        LL_GPIO_SetPinOutputType(GPIOB, LED_PORTB, LL_GPIO_OUTPUT_OPENDRAIN);
        LL_GPIO_SetPinOutputType(GPIOF, LED_PORTF, LL_GPIO_OUTPUT_OPENDRAIN);
        GPIOA->ODR |= LED_PORTA;
        GPIOB->ODR |= LED_PORTB;
        GPIOF->ODR |= LED_PORTF;
        break;
    /*  打开LED显示 */
    case TK_LED_ON:
    {
#if (TK_LED_NUM == 1)
        seg1 = led_offset;
        com = led_offset;
#else
        seg1 = LED_BANK[led_offset][0];
        seg2 = LED_BANK[led_offset][1];
#if (TK_LED_NUM == 3)
        seg3 = LED_BANK[led_offset][2];
#endif
        com = LED_BANK[led_offset][0];
#endif
        led_com = seg1 >> 3;
        led_seg = seg1 % 8;
        /*  点亮对应的LED   */
        if (led_data[led_com] & (1 << led_seg))
        {
            GPIOxH = GPIO_PORT(SEG_TBL[seg1][0]);
            PINxH = GPIO_PIN(SEG_TBL[seg1][0]);
            LL_GPIO_SetPinOutputType(GPIOxH, PINxH, LL_GPIO_OUTPUT_PUSHPULL);
            out = 0X01;
        }
#if (TK_LED_NUM > 1)
        if (seg2 != 0XFF)
        {
            led_com = seg2 >> 3;
            led_seg = seg2 % 8;
            if (led_data[led_com] & (1 << led_seg))
            {
                GPIOxH = GPIO_PORT(SEG_TBL[seg2][0]);
                PINxH = GPIO_PIN(SEG_TBL[seg2][0]);
                LL_GPIO_SetPinOutputType(GPIOxH, PINxH, LL_GPIO_OUTPUT_PUSHPULL);
                out = 0X01;
            }
        }
#endif
#if (TK_LED_NUM > 2)
        if (seg3 != 0XFF)
        {
            led_com = seg3 >> 3;
            led_seg = seg3 % 8;
            if (led_data[led_com] & (1 << led_seg))
            {
                GPIOxH = GPIO_PORT(SEG_TBL[seg3][0]);
                PINxH = GPIO_PIN(SEG_TBL[seg3][0]);
                LL_GPIO_SetPinOutputType(GPIOxH, PINxH, LL_GPIO_OUTPUT_PUSHPULL);
                out = 0X01;
            }
        }
#endif
        /*  当前IO口输出0   */
        if (out)
        {
            GPIOxL = GPIO_PORT(SEG_TBL[com][1]);
            PINxL = GPIO_PIN(SEG_TBL[com][1]);
            GPIOxL->BRR = PINxL;
        }
    }
    break;
    /*  显示下一个数据  */
    case TK_LED_COL:
        /*  */
        do
        {
#if (TK_LED_NUM == 1)
            if (++led_offset > 55)
                led_offset = 0;
#elif (TK_LED_NUM == 2)
            if (++led_offset > 31)
                led_offset = 0;
#elif (TK_LED_NUM == 3)
            if (++led_offset > 26)
                led_offset = 0;
#endif
#if (TK_LED_NUM == 1)
            seg1 = led_offset;
#else
            seg1 = LED_BANK[led_offset][0];
#endif
            led_com = seg1 >> 3;
            led_seg = seg1 % 8;
        }
        while (led_seg > X_END || led_com > Y_END);
        break;
    }
}
#endif
#endif
