
#if 0

#include "system/includes.h"
#include "audio_spectrum.h"


#define LED_NUM_MAX         (18 * 6)
static u8 led_rgb_val_buf[24 * LED_NUM_MAX] __attribute__((aligned(4)));

void led_spi_init(void);
void led_spi_send_rgbbuf_isr(u8 *rgb_buf, u16 led_num);
void led_spi_rgb_to_24byte(u8 r, u8 g, u8 b, u8 *buf, int idx);

/***********************************************************************************************
 *                      接口替换区
***********************************************************************************************/
#define led_init()                          led_spi_init()
#define led_rgb_to_buf(r,g,b,buf,idx)       led_spi_rgb_to_24byte(r,g,b,buf,idx)
#define led_send_rgbbuf(buf,num)            led_spi_send_rgbbuf_isr(buf,num)


/***********************************************************************************************
                 ********            **
r:              *        *          *
               *          *        *
        *******            ********
        **           ********
g:        *         *        *
           *       *          *
            *******            ********
        ******           ********
b:            *         *        *
               *       *          *
                *******            ****
 * 流水灯控制驱动原理：
 *1. 每个模式都会一个周期                                                                      ***********
 *2. 以一个灯为例，一个模式周期内，又分三个颜色，即每个颜色各有各的周期。                     *           *
 *3. 最核心的思维是：一个灯的三个颜色的地位是相等的，灯与灯之间，每个灯的地位是相等。        *             *
 *4. 每个颜色在一个周期里分为几个阶段：最暗到最亮，最亮维持，最亮到最暗，最暗维持    ********               *******
 *5. 颜色之间可以存在相位差，
 *6. 灯与灯之间的计数值可以存在相位差
***********************************************************************************************/

struct led_rgb_t {
    u8 mode_idx;                                //灯亮的模式号
    u8 div_sec_num;                             //一条灯带分几段
    u8 sec_led_num;                             //每段灯带几个灯
    u8 cnt_freq;                                //CNT多久加一次，单位10ms，这个值越大，灯变化越慢
    u8 rgb_val_max[3];                          //可配置某颜色值的最大值，一般是255
    u8 rgb_val_min[3];                          //可配置某颜色值的最大值，一般是0
    int cnt[3];                                 //单个灯，颜色的变化计数值，cnt的初值，就是三个颜色的相位差。
    int next_cnt_dir[3];                        //同个颜色灯与灯之间的传递方向和传递间隔, 下一个灯的cnt是上一个灯的cnt+next_cnt_dir
    int next_sec_cnt_phase[3];                  //同个颜色段与段之间的相位差,即下一段灯带的颜色cnt初始值是上一段灯带的cnt+next_sec_cnt_phase
    int cnt_unit[3];                            //CNT加一次加多少，这个值越大，灯变化越快，CNT加到最大周期值后，又从0开始加
    int cnt_max_prd[3];                         //一个颜色的整个模式的周期, 不管CNT怎么加，都映射在这个周期里，即cnt %= cnt_max_prd
    int pu_cnt_start[3];                        //一个周期内，颜色值上升开始的时间，即这个颜色开始亮了
    int pu_cnt_end[3];                          //一个周期内，颜色值上升结束的时间，即颜色值达到最大值
    int keep_cnt_start[3];                      //一个周期内，颜色值维持最大的开始时间，一般为颜色值上升结束的时间
    int keep_cnt_end[3];                        //一个周期内，颜色值维持最大的结束时间
    int pd_cnt_start[3];                        //一个周期内，颜色值下降开始的时间，一般为颜色值维持最大的结束时间
    int pd_cnt_end[3];                          //一个周期内，颜色值下降结束的时间，即颜色值没有为0了
};

static struct led_rgb_t mode0_led_rgb = {
    .mode_idx           = 0,
    .div_sec_num        = 6,
    .sec_led_num        = 18,
    .cnt_freq           = 1,
//r:
    .rgb_val_max[   0]  = 255,      .rgb_val_min[   0]  = 0,
    .cnt[           0]  = 0,        .next_cnt_dir[  0]  = -10,
    .cnt_unit[      0]  = 1,        .cnt_max_prd[   0]  = 90,
    .pu_cnt_start[  0]  = 0,        .pu_cnt_end[    0]  = 30,
    .keep_cnt_start[0]  = 30,       .keep_cnt_end[  0]  = 30,
    .pd_cnt_start[  0]  = 30,       .pd_cnt_end[    0]  = 60,
//g:
    .rgb_val_max[   1]  = 255,      .rgb_val_min[   1]  = 0,
    .cnt[           1]  = 30,       .next_cnt_dir[  1]  = -10,
    .cnt_unit[      1]  = 1,        .cnt_max_prd[   1]  = 90,
    .pu_cnt_start[  1]  = 0,        .pu_cnt_end[    1]  = 30,
    .keep_cnt_start[1]  = 30,       .keep_cnt_end[  1]  = 30,
    .pd_cnt_start[  1]  = 30,       .pd_cnt_end[    1]  = 60,
//b:
    .rgb_val_max[   2]  = 255,      .rgb_val_min[   2]  = 0,
    .cnt[           2]  = 60,       .next_cnt_dir[  2]  = -10,
    .cnt_unit[      2]  = 1,        .cnt_max_prd[   2]  = 90,
    .pu_cnt_start[  2]  = 0,        .pu_cnt_end[    2]  = 30,
    .keep_cnt_start[2]  = 30,       .keep_cnt_end[  2]  = 30,
    .pd_cnt_start[  2]  = 30,       .pd_cnt_end[    2]  = 60,
};
static struct led_rgb_t mode1_led_rgb = {
    .mode_idx           = 1,
    .div_sec_num        = 6,
    .sec_led_num        = 18,
    .cnt_freq           = 1,
//r:
    .rgb_val_max[   0]  = 255,      .rgb_val_min[   0]  = 0,
    .cnt[           0]  = 0,        .next_cnt_dir[  0]  = 6,
    .cnt_unit[      0]  = 1,        .cnt_max_prd[   0]  = 108,
    .pu_cnt_start[  0]  = 0,        .pu_cnt_end[    0]  = 0,
    .keep_cnt_start[0]  = 0,        .keep_cnt_end[  0]  = 54,
    .pd_cnt_start[  0]  = 54,       .pd_cnt_end[    0]  = 54,
//g:
    .rgb_val_max[   1]  = 255,      .rgb_val_min[   1]  = 0,
    .cnt[           1]  = 36,       .next_cnt_dir[  1]  = 6,
    .cnt_unit[      1]  = 1,        .cnt_max_prd[   1]  = 108,
    .pu_cnt_start[  1]  = 0,        .pu_cnt_end[    1]  = 0,
    .keep_cnt_start[1]  = 0,        .keep_cnt_end[  1]  = 54,
    .pd_cnt_start[  1]  = 54,       .pd_cnt_end[    1]  = 54,
//b:
    .rgb_val_max[   2]  = 255,      .rgb_val_min[   2]  = 0,
    .cnt[           2]  = 72,       .next_cnt_dir[  2]  = 6,
    .cnt_unit[      2]  = 1,        .cnt_max_prd[   2]  = 108,
    .pu_cnt_start[  2]  = 0,        .pu_cnt_end[    2]  = 0,
    .keep_cnt_start[2]  = 0,        .keep_cnt_end[  2]  = 54,
    .pd_cnt_start[  2]  = 54,       .pd_cnt_end[    2]  = 54,
};
static struct led_rgb_t mode2_led_rgb = {
    .mode_idx           = 2,
    .div_sec_num        = 6,
    .sec_led_num        = 18,
    .cnt_freq           = 1,
//r:
    .rgb_val_max[   0]  = 255,      .rgb_val_min[   0]  = 0,
    .cnt[           0]  = 0,        .next_cnt_dir[  0]  = -5,
    .cnt_unit[      0]  = 1,        .cnt_max_prd[   0]  = 90,
    .pu_cnt_start[  0]  = 0,        .pu_cnt_end[    0]  = 0,
    .keep_cnt_start[0]  = 0,        .keep_cnt_end[  0]  = 30,
    .pd_cnt_start[  0]  = 30,       .pd_cnt_end[    0]  = 30,
//g:
    .rgb_val_max[   1]  = 255,      .rgb_val_min[   1]  = 0,
    .cnt[           1]  = 30,       .next_cnt_dir[  1]  = -5,
    .cnt_unit[      1]  = 1,        .cnt_max_prd[   1]  = 90,
    .pu_cnt_start[  1]  = 0,        .pu_cnt_end[    1]  = 0,
    .keep_cnt_start[1]  = 0,        .keep_cnt_end[  1]  = 30,
    .pd_cnt_start[  1]  = 30,       .pd_cnt_end[    1]  = 30,
//b:
    .rgb_val_max[   2]  = 255,      .rgb_val_min[   2]  = 0,
    .cnt[           2]  = 60,       .next_cnt_dir[  2]  = -5,
    .cnt_unit[      2]  = 1,        .cnt_max_prd[   2]  = 90,
    .pu_cnt_start[  2]  = 0,        .pu_cnt_end[    2]  = 0,
    .keep_cnt_start[2]  = 0,        .keep_cnt_end[  2]  = 30,
    .pd_cnt_start[  2]  = 30,       .pd_cnt_end[    2]  = 30,
};
static struct led_rgb_t mode3_led_rgb = {
    .mode_idx           = 3,
    .div_sec_num        = 6,
    .sec_led_num        = 18,
    .cnt_freq           = 1,
//r:
    .rgb_val_max[   0]  = 255,      .rgb_val_min[   0]  = 0,
    .cnt[           0]  = 0,        .next_cnt_dir[  0]  = 2,
    .cnt_unit[      0]  = 1,        .cnt_max_prd[   0]  = 108,
    .pu_cnt_start[  0]  = 0,        .pu_cnt_end[    0]  = 0,
    .keep_cnt_start[0]  = 0,        .keep_cnt_end[  0]  = 36,
    .pd_cnt_start[  0]  = 36,       .pd_cnt_end[    0]  = 36,
//g:
    .rgb_val_max[   1]  = 255,      .rgb_val_min[   1]  = 0,
    .cnt[           1]  = 36,       .next_cnt_dir[  1]  = 2,
    .cnt_unit[      1]  = 1,        .cnt_max_prd[   1]  = 108,
    .pu_cnt_start[  1]  = 0,        .pu_cnt_end[    1]  = 0,
    .keep_cnt_start[1]  = 0,        .keep_cnt_end[  1]  = 36,
    .pd_cnt_start[  1]  = 36,       .pd_cnt_end[    1]  = 36,
//b:
    .rgb_val_max[   2]  = 255,      .rgb_val_min[   2]  = 0,
    .cnt[           2]  = 72,       .next_cnt_dir[  2]  = 2,
    .cnt_unit[      2]  = 1,        .cnt_max_prd[   2]  = 108,
    .pu_cnt_start[  2]  = 0,        .pu_cnt_end[    2]  = 0,
    .keep_cnt_start[2]  = 0,        .keep_cnt_end[  2]  = 36,
    .pd_cnt_start[  2]  = 36,       .pd_cnt_end[    2]  = 36,
};
static struct led_rgb_t mode4_led_rgb = {
    .mode_idx           = 4,
    .div_sec_num        = 6,
    .sec_led_num        = 18,
    .cnt_freq           = 1,
//r:
    .rgb_val_max[   0]  = 255,      .rgb_val_min[   0]  = 0,
    .cnt[           0]  = 0,        .next_cnt_dir[  0]  = -12,
    .cnt_unit[      0]  = 1,        .cnt_max_prd[   0]  = 108,
    .pu_cnt_start[  0]  = 0,        .pu_cnt_end[    0]  = 12,
    .keep_cnt_start[0]  = 12,       .keep_cnt_end[  0]  = 24,
    .pd_cnt_start[  0]  = 24,       .pd_cnt_end[    0]  = 36,
//g:
    .rgb_val_max[   1]  = 255,      .rgb_val_min[   1]  = 0,
    .cnt[           1]  = 36,       .next_cnt_dir[  1]  = -12,
    .cnt_unit[      1]  = 1,        .cnt_max_prd[   1]  = 108,
    .pu_cnt_start[  1]  = 0,        .pu_cnt_end[    1]  = 12,
    .keep_cnt_start[1]  = 12,       .keep_cnt_end[  1]  = 24,
    .pd_cnt_start[  1]  = 24,       .pd_cnt_end[    1]  = 36,
//b:
    .rgb_val_max[   2]  = 255,      .rgb_val_min[   2]  = 0,
    .cnt[           2]  = 72,       .next_cnt_dir[  2]  = -12,
    .cnt_unit[      2]  = 1,        .cnt_max_prd[   2]  = 108,
    .pu_cnt_start[  2]  = 0,        .pu_cnt_end[    2]  = 12,
    .keep_cnt_start[2]  = 12,       .keep_cnt_end[  2]  = 24,
    .pd_cnt_start[  2]  = 24,       .pd_cnt_end[    2]  = 36,
};
static struct led_rgb_t mode5_led_rgb = {
    .mode_idx           = 5,
    .div_sec_num        = 6,
    .sec_led_num        = 18,
    .cnt_freq           = 1,
//r:
    .rgb_val_max[   0]  = 255,      .rgb_val_min[   0]  = 0,
    .cnt[           0]  = 0,        .next_cnt_dir[  0]  = 2,
    .cnt_unit[      0]  = 1,        .cnt_max_prd[   0]  = 108,
    .pu_cnt_start[  0]  = 0,        .pu_cnt_end[    0]  = 0,
    .keep_cnt_start[0]  = 0,        .keep_cnt_end[  0]  = 2,
    .pd_cnt_start[  0]  = 2,        .pd_cnt_end[    0]  = 2,
//g:
    .rgb_val_max[   1]  = 255,      .rgb_val_min[   1]  = 0,
    .cnt[           1]  = 36,       .next_cnt_dir[  1]  = 2,
    .cnt_unit[      1]  = 1,        .cnt_max_prd[   1]  = 108,
    .pu_cnt_start[  1]  = 0,        .pu_cnt_end[    1]  = 0,
    .keep_cnt_start[1]  = 0,        .keep_cnt_end[  1]  = 2,
    .pd_cnt_start[  1]  = 2,        .pd_cnt_end[    1]  = 2,
//b:
    .rgb_val_max[   2]  = 255,      .rgb_val_min[   2]  = 0,
    .cnt[           2]  = 72,       .next_cnt_dir[  2]  = 2,
    .cnt_unit[      2]  = 1,        .cnt_max_prd[   2]  = 108,
    .pu_cnt_start[  2]  = 0,        .pu_cnt_end[    2]  = 0,
    .keep_cnt_start[2]  = 0,        .keep_cnt_end[  2]  = 2,
    .pd_cnt_start[  2]  = 2,        .pd_cnt_end[    2]  = 2,
};
static struct led_rgb_t mode6_led_rgb = {
    .mode_idx           = 6,
    .div_sec_num        = 4,
    .sec_led_num        = 6,
    .cnt_freq           = 1,
//r:
    .rgb_val_max[   0]  = 255,      .rgb_val_min[   0]  = 200,
    .cnt[           0]  = 0,        .next_cnt_dir[  0]  = -18,
    .cnt_unit[      0]  = 1,        .cnt_max_prd[   0]  = 48,
    .pu_cnt_start[  0]  = 0,        .pu_cnt_end[    0]  = 0,
    .keep_cnt_start[0]  = 0,        .keep_cnt_end[  0]  = 24,
    .pd_cnt_start[  0]  = 24,        .pd_cnt_end[    0]  = 24,
    .next_sec_cnt_phase[0] = 18,
//g:
    .rgb_val_max[   1]  = 128,      .rgb_val_min[   1]  = 32,
    .cnt[           1]  = 0,        .next_cnt_dir[  1]  = 18,
    .cnt_unit[      1]  = 0,        .cnt_max_prd[   1]  = 108,
    .pu_cnt_start[  1]  = 0,        .pu_cnt_end[    1]  = 0,
    .keep_cnt_start[1]  = 0,        .keep_cnt_end[  1]  = 1,
    .pd_cnt_start[  1]  = 1,        .pd_cnt_end[    1]  = 108,
};
static struct led_rgb_t mode7_led_rgb = {
    .mode_idx           = 7,
    .div_sec_num        = 6,
    .sec_led_num        = 18,
    .cnt_freq           = 1,
//r:
    .rgb_val_max[   0]  = 255,      .rgb_val_min[   0]  = 255,
};
struct led_rgb_t *led_rgb_table[] = {
    &mode0_led_rgb,//流水灯
    &mode1_led_rgb,//流水灯
    &mode2_led_rgb,//流水灯
    &mode3_led_rgb,//流水灯
    &mode4_led_rgb,//流水灯
    &mode5_led_rgb,//流水灯
    &mode6_led_rgb,//用于4X6火焰效果
    &mode7_led_rgb,//用于显示播歌的频点能量
};

extern spectrum_fft_hdl *spec_hdl;
static short db_data_old[32];
static short led_on_table[32];
/*
 * @brief 获取频谱能量,板级头文件要定义音频的宏#define AUDIO_SPECTRUM_CONFIG  1  //频响能量值获取接口
 * @param p 音频接口的结构体参数
 */
void led_get_spectrum(void *p)
{
    spectrum_fft_hdl *hdl = p;
    if (hdl) {
        u8 db_num = audio_spectrum_fft_get_num(hdl);//获取频谱个数
        short *db_data = audio_spectrum_fft_get_val(hdl);//获取存储频谱值得地址
        if (!db_data) {
            return;
        }
        for (int i = 0; i < db_num; i++) {
            if (i < 32) {
                led_on_table[i] = db_data[i] - db_data_old[i];
                db_data_old[i] = db_data[i];
            }
        }
    }
}

/*
 * @brief 一段灯带亮灯的数量
 * @param led_rgb 该模式结构体参数
 * @param sec_num 第几段灯带
 * @return 可以亮灯的数量
 */
int get_led_sec_on_num(struct led_rgb_t *led_rgb, int sec_num)
{
    int on_num = led_rgb->sec_led_num;
    switch (led_rgb->mode_idx) {
    case 0:
        break;
    case 1:
        break;
    case 2:
        break;
    case 3:
        break;
    case 4:
        break;
    case 5:
        break;
    case 6:
        break;
    case 7:
        if (spec_hdl) {
            short sum0 = 0;
            short sum1 = 0;
            int tmp = 32 / led_rgb->div_sec_num;
            for (short i = 0; i < tmp; i ++) {
                sum0 += led_on_table[i + sec_num * tmp];
                sum1 += db_data_old[i + sec_num * tmp];
            }
            sum0 /= 5;
            sum1 /= 5;
            short num = ((sum1 * led_rgb->sec_led_num / 90) + sum0);
            if (num < 0) {
                num = 0;
            }
            on_num = num % led_rgb->sec_led_num;
        }
        break;
    }
    return on_num;
}

/*
 * @brief 约束CNT值在周期值内
 * @param led_rgb 该模式结构体参数
 * @param colour 颜色号：0,红色  1,绿色  2,蓝色
 * @param cnt 颜色对应的计数值
 * @return 映射后的值
 */
int get_map_cnt(struct led_rgb_t *led_rgb, int colour, int cnt)
{
    if (led_rgb->cnt_max_prd[colour] == 0) {
        return 0;
    }
    while (cnt < 0) {
        cnt += led_rgb->cnt_max_prd[colour];
    }
    cnt %= led_rgb->cnt_max_prd[colour];
    return cnt;
}

/*
 * @brief 将CNT值转换为RGB值
 * @param led_rgb 该模式结构体参数
 * @param colour 颜色号：0,红色  1,绿色  2,蓝色
 * @param cnt 颜色对应的计数值
 * @return 对应的颜色亮度值
 */
u8 led_cnt_to_rgb_val(struct led_rgb_t *led_rgb, int colour, int cnt)
{
    u8 rgb_val = led_rgb->rgb_val_min[colour];
    int tmp_cnt = 0;
    int i = colour;
    int rgb_val_delta = led_rgb->rgb_val_max[i] - led_rgb->rgb_val_min[i];
    if ((led_rgb->pu_cnt_start[i] <= cnt) && (cnt < led_rgb->pu_cnt_end[i])) {              //递增区间
        tmp_cnt = cnt - led_rgb->pu_cnt_start[i] + 1;
        rgb_val = led_rgb->rgb_val_min[i] + (tmp_cnt * rgb_val_delta / (led_rgb->pu_cnt_end[i] - led_rgb->pu_cnt_start[i]));
    } else if ((led_rgb->keep_cnt_start[i] <= cnt) && (cnt < led_rgb->keep_cnt_end[i])) {   //高维持区间
        rgb_val = led_rgb->rgb_val_max[i];
    } else if ((led_rgb->pd_cnt_start[i] <= cnt) && (cnt < led_rgb->pd_cnt_end[i])) {       //递减区间
        tmp_cnt = led_rgb->pd_cnt_end[i] - cnt - 1;
        rgb_val = led_rgb->rgb_val_min[i] + (tmp_cnt * rgb_val_delta / (led_rgb->pd_cnt_end[i] - led_rgb->pd_cnt_start[i]));
    }
    return rgb_val;
}

/*
 * @brief 更新RGB的DMA buf数据，并发送出去，更新灯带
 * @param led_rgb 该模式结构体参数
 * @param cnt 基础节拍计数值
 */
void led_rgb_upgrade(struct led_rgb_t *led_rgb, int cnt)
{
    u8 r_val = 0;
    u8 g_val = 0;
    u8 b_val = 0;
    if ((cnt % led_rgb->cnt_freq) == 0) {
        led_rgb->cnt[0] = get_map_cnt(led_rgb, 0, led_rgb->cnt[0] + led_rgb->cnt_unit[0]);
        led_rgb->cnt[1] = get_map_cnt(led_rgb, 1, led_rgb->cnt[1] + led_rgb->cnt_unit[1]);
        led_rgb->cnt[2] = get_map_cnt(led_rgb, 2, led_rgb->cnt[2] + led_rgb->cnt_unit[2]);
        for (int i = 0; i < led_rgb->div_sec_num; i ++) {
            int led_on_num = get_led_sec_on_num(led_rgb, i);
            for (int j = 0; j < led_rgb->sec_led_num; j ++) {
                r_val = led_cnt_to_rgb_val(led_rgb, 0, get_map_cnt(led_rgb, 0, led_rgb->cnt[0] + (i * led_rgb->next_sec_cnt_phase[0] + j) * led_rgb->next_cnt_dir[0]));
                g_val = led_cnt_to_rgb_val(led_rgb, 1, get_map_cnt(led_rgb, 1, led_rgb->cnt[1] + (i * led_rgb->next_sec_cnt_phase[1] + j) * led_rgb->next_cnt_dir[1]));
                b_val = led_cnt_to_rgb_val(led_rgb, 2, get_map_cnt(led_rgb, 2, led_rgb->cnt[2] + (i * led_rgb->next_sec_cnt_phase[2] + j) * led_rgb->next_cnt_dir[2]));
                if (j >= led_on_num) {
                    r_val = 0;
                    g_val = 0;
                    b_val = 0;
                }
                led_rgb_to_buf(r_val, g_val, b_val, led_rgb_val_buf, i * led_rgb->sec_led_num + j);
            }
        }
        led_send_rgbbuf(led_rgb_val_buf, led_rgb->div_sec_num * led_rgb->sec_led_num);
    }
}

/*
 * @brief 定时轮询各模式
 */
void led_rgb_scan(void *priv)
{
    static u32 step_cnt = 0;
    static u32 mode_idx = 0;
    static struct led_rgb_t *led_rgb = NULL;
    if ((step_cnt % 800) == 0) { //8s
        step_cnt = 0;
        led_rgb = led_rgb_table[mode_idx];
        mode_idx ++;
        if (mode_idx >= (sizeof(led_rgb_table) / 4)) {
            mode_idx = 0;
        }
    }
    led_rgb_upgrade(led_rgb, step_cnt);
    step_cnt ++;
}

void my_led_test(void)
{
    printf("******************  led test  *******************\n");
    led_init();
    sys_timer_add(NULL, led_rgb_scan, 10);
    sys_timer_add(spec_hdl, led_get_spectrum, 100);//定期获取能量值
}

#endif

