/*
 * ****************************************************
 * @file    : led.c
 * @brief   : Addressable-LED Program Body
 * @author  : sohee kim / Something by People
 * @data    : 2023. 10. 23
 * ****************************************************
 */
#include "led.h"

//#define __DEBUG__

#ifdef  __DEBUG__
#define DEBUG_printf                UART3_printf
#else
#define DEBUG_printf                Dummy_printf
#endif

#define ESC                         ((uint8_t)255)       //0xFF

#define COM_BEGIN                   ((uint8_t)252)       //0xFC    //Loop Begin
#define COM_END                     ((uint8_t)253)       //0xFD    //Loop End
#define COM_EXIT                    ((uint8_t)255)       //0xFF    //Exit

#define COM_WAIT                    ((uint8_t)255)       //0xFF    //Wait

#define COM_A_DEC                   ((uint8_t)125)
#define COM_A_HLD                   ((uint8_t)126)
#define COM_A_INC                   ((uint8_t)127)

#define COM_L_DEC                   ((uint8_t)189)
#define COM_L_HLD                   ((uint8_t)190)
#define COM_L_INC                   ((uint8_t)191)

#define COM_R_DEC                   ((uint8_t)249)
#define COM_R_HLD                   ((uint8_t)250)
#define COM_R_INC                   ((uint8_t)251)

#define D10                         ((uint8_t)251)      //-10
#define DEC                         ((uint8_t)252)      //- 1
#define HLD                         ((uint8_t)253)      //+-0
#define INC                         ((uint8_t)254)      //+ 1
#define I10                         ((uint8_t)255)      //+10

#define LED_PutData(s)              UART_PutData(LED_PORT, (uint8_t *)(s), LED_PACKET_SIZE)

const uint8_t Inc_Dec[5] = {0xF6, 0xFF, 0, 1, 10};

const uint8_t LED_Stream0[][LED_PACKET_SIZE+1] = {
// Time   Command   R1  G1  B1  R2  G2  B2
// 10ms
  { ESC, COM_BEGIN,255,  0,  0,  0,  0,  0},
  {   1, LED_A( 0),  0,  0,  0,  0,  0,  0},

  {   1, LED_1( 1),  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN,100,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,INC,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,  0,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  {   1, LED_1(60),100,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN,100,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,DEC,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,100,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  {   1, LED_1( 1),  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN,100,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,  0,INC,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,  0,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN,100,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,  0,DEC,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,  0,100,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  {   1, LED_1( 1),  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN,100,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,  0,  0,INC,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,  0,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN,100,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,  0,  0,DEC,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,  0,  0,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_EXIT ,  0,  0,  0,  0,  0,  0}
};

const uint8_t LED_Stream1[][LED_PACKET_SIZE+1] = {
// Time   Command   R1  G1  B1  R2  G2  B2
// 10ms
  { ESC, COM_BEGIN,255,  0,  0,  0,  0,  0},
  {   1, LED_A( 0),  0,  0,  0,  0,  0,  0},

  {   1, LED_1( 1),  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 10,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,I10,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,  0,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  {   1, LED_1(60),100,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 10,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,D10,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,100,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  {   1, LED_1( 1),  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 10,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,  0,I10,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,  0,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 10,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,  0,D10,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,  0,100,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  {   1, LED_1( 1),  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 10,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,  0,  0,I10,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,  0,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 10,  0,  0,  0,  0,  0},
  {   1, COM_A_HLD,  0,  0,D10,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,  0,  0,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { 100, COM_WAIT ,  0,  0,  0,  0,  0,  0},

  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_EXIT ,  0,  0,  0,  0,  0,  0}
};

const uint8_t LED_Stream2[][LED_PACKET_SIZE+1] = {
// Time   Command   R1  G1  B1  R2  G2  B2
// 10ms
  { ESC, COM_BEGIN,  1,  0,  0,  0,  0,  0},

  {   1, LED_A( 0),100,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,100,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,100,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_A( 0),  0,100,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,  0,100,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,  0,100,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_A( 0),  0,  0,100,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,  0,  0,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,  0,  0,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_A( 0),100,  0,100,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,100,  0,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,100,  0,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_A( 0),100,100,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,100,100,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,100,100,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_A( 0),  0,100,100,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,  0,100,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,  0,100,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_A( 0),100,100,100,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_INC,100,100,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 60,  0,  0,  0,  0,  0},
  {   1, COM_A_DEC,100,100,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_EXIT ,  0,  0,  0,  0,  0,  0}
};

const uint8_t LED_Stream3[][LED_PACKET_SIZE+1] = {
// Time   Command   R1  G1  B1  R2  G2  B2
// 10ms
  { ESC, COM_BEGIN,  1,  0,  0,  0,  0,  0},

  {   1, LED_L( 0),100,  0,  0,  0,  0,  0},
  {   1, LED_R( 0),100,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,100,  0,  0,  0,  0,  0},
  {   1, COM_R_INC,100,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,100,  0,  0,  0,  0,  0},
  {   1, COM_R_DEC,100,  0,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L( 0),  0,100,  0,  0,  0,  0},
  {   1, LED_R( 0),  0,100,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,  0,100,  0,  0,  0,  0},
  {   1, COM_R_INC,  0,100,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,  0,100,  0,  0,  0,  0},
  {   1, COM_R_DEC,  0,100,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L( 0),  0,  0,100,  0,  0,  0},
  {   1, LED_R( 0),  0,  0,100,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,  0,  0,100,  0,  0,  0},
  {   1, COM_R_INC,  0,  0,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,  0,  0,100,  0,  0,  0},
  {   1, COM_R_DEC,  0,  0,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L( 0),100,  0,100,  0,  0,  0},
  {   1, LED_R( 0),100,  0,100,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,100,  0,100,  0,  0,  0},
  {   1, COM_R_INC,100,  0,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,100,  0,100,  0,  0,  0},
  {   1, COM_R_DEC,100,  0,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L( 0),100,100,  0,  0,  0,  0},
  {   1, LED_R( 0),100,100,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,100,100,  0,  0,  0,  0},
  {   1, COM_R_INC,100,100,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,100,100,  0,  0,  0,  0},
  {   1, COM_R_DEC,100,100,  0,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L( 0),  0,100,100,  0,  0,  0},
  {   1, LED_R( 0),  0,100,100,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,  0,100,100,  0,  0,  0},
  {   1, COM_R_INC,  0,100,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,  0,100,100,  0,  0,  0},
  {   1, COM_R_DEC,  0,100,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L( 0),100,100,100,  0,  0,  0},
  {   1, LED_R( 0),100,100,100,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,100,100,100,  0,  0,  0},
  {   1, COM_R_INC,100,100,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,100,100,100,  0,  0,  0},
  {   1, COM_R_DEC,100,100,100,  0,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_EXIT ,  0,  0,  0,  0,  0,  0}
};

const uint8_t LED_Stream4[][LED_PACKET_SIZE+1] = {
// Time   Command   R1  G1  B1  R2  G2  B2
// 10ms
  { ESC, COM_BEGIN,  1,  0,  0,  0,  0,  0},

  {   1, LED_L(30),  0,  0,  0,100,  0,  0},
  {   1, LED_R(30),  0,  0,  0,100,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,  0,  0,  0,100,  0,  0},
  {   1, COM_R_DEC,  0,  0,  0,100,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,  0,  0,  0,100,  0,  0},
  {   1, COM_R_INC,  0,  0,  0,100,  0,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L(30),  0,  0,  0,  0,100,  0},
  {   1, LED_R(30),  0,  0,  0,  0,100,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,  0,  0,  0,  0,100,  0},
  {   1, COM_R_DEC,  0,  0,  0,  0,100,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,  0,  0,  0,  0,100,  0},
  {   1, COM_R_INC,  0,  0,  0,  0,100,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L(30),  0,  0,  0,  0,  0,100},
  {   1, LED_R(30),  0,  0,  0,  0,  0,100},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,  0,  0,  0,  0,  0,100},
  {   1, COM_R_DEC,  0,  0,  0,  0,  0,100},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,  0,  0,  0,  0,  0,100},
  {   1, COM_R_INC,  0,  0,  0,  0,  0,100},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L(30),  0,  0,  0,100,  0,100},
  {   1, LED_R(30),  0,  0,  0,100,  0,100},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,  0,  0,  0,100,  0,100},
  {   1, COM_R_DEC,  0,  0,  0,100,  0,100},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,  0,  0,  0,100,  0,100},
  {   1, COM_R_INC,  0,  0,  0,100,  0,100},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L(30),  0,  0,  0,100,100,  0},
  {   1, LED_R(30),  0,  0,  0,100,100,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,  0,  0,  0,100,100,  0},
  {   1, COM_R_DEC,  0,  0,  0,100,100,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,  0,  0,  0,100,100,  0},
  {   1, COM_R_INC,  0,  0,  0,100,100,  0},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L(30),  0,  0,  0,  0,100,100},
  {   1, LED_R(30),  0,  0,  0,  0,100,100},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,  0,  0,  0,  0,100,100},
  {   1, COM_R_DEC,  0,  0,  0,  0,100,100},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,  0,  0,  0,  0,100,100},
  {   1, COM_R_INC,  0,  0,  0,  0,100,100},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  {   1, LED_L(30),  0,  0,  0,100,100,100},
  {   1, LED_R(30),  0,  0,  0,100,100,100},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_DEC,  0,  0,  0,100,100,100},
  {   1, COM_R_DEC,  0,  0,  0,100,100,100},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_BEGIN, 30,  0,  0,  0,  0,  0},
  {   1, COM_L_INC,  0,  0,  0,100,100,100},
  {   1, COM_R_INC,  0,  0,  0,100,100,100},
  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},

  { ESC, COM_END  ,  0,  0,  0,  0,  0,  0},
  { ESC, COM_EXIT ,  0,  0,  0,  0,  0,  0}
};

const uint8_t LED_Stream5[10][LED_PACKET_SIZE+1];
const uint8_t LED_Stream6[10][LED_PACKET_SIZE+1];
const uint8_t LED_Stream7[10][LED_PACKET_SIZE+1];
const uint8_t LED_Stream8[10][LED_PACKET_SIZE+1];
const uint8_t LED_Stream9[10][LED_PACKET_SIZE+1];

uint8_t *LED_Stream[] = { (uint8_t*)LED_Stream0, (uint8_t*)LED_Stream1, (uint8_t*)LED_Stream2, (uint8_t*)LED_Stream3, (uint8_t*)LED_Stream4,
                          (uint8_t*)LED_Stream5, (uint8_t*)LED_Stream6, (uint8_t*)LED_Stream7, (uint8_t*)LED_Stream8, (uint8_t*)LED_Stream9
};


uint8_t*  LED_Stream_;
#define   LED_Stream(i, j)           (*(LED_Stream_+(i)*(LED_PACKET_SIZE+1)+(j)))

void LED_Send(uint8_t n, uint8_t red, uint8_t green, uint8_t blue, uint8_t red2, uint8_t green2, uint8_t blue2)
{
  uint8_t buffer[LED_PACKET_SIZE] = {n, red, green, blue, red2, green2, blue2};
  Stop_LED_Task();
  LED_PutData(buffer);
/*
  uint8_t com;
  com = n>>6;
  if(com)       com--;        //com : 0~2

  LED_Buffer[com][0] = n;
  LED_Buffer[com][1] = red;
  LED_Buffer[com][2] = green;
  LED_Buffer[com][3] = blue;
  LED_Buffer[com][4] = red2;
  LED_Buffer[com][5] = green2;
  LED_Buffer[com][6] = blue2;

  Stop_LED_Task();
  LED_PutData(LED_Buffer[com]);
*/
}

uint8_t Flag_LED_Task = 0;

volatile uint16_t  LED_Index  = 0;
volatile uint8_t   LED_10msec = 0;

uint8_t LED_Buffer[3][LED_PACKET_SIZE];

#define MAX_NESTED_LOOP             8
volatile int8_t    LED_Loop_Index = -1;                  //0~(MAX_NESTED_LOOP-1)
volatile uint16_t  LED_Loop_Begin[MAX_NESTED_LOOP];
volatile uint8_t   LED_Loop_Count[MAX_NESTED_LOOP];

void LED_Task(void)
{
  if(Flag_LED_Task) {
    if(LED_10msec>0) {
      if(--LED_10msec == 0) {
        return;
      }
    }

    while(LED_10msec==0) {
      if(LED_Stream(LED_Index,0) == ESC) {
        if(LED_Stream(LED_Index,1) == COM_EXIT) {
          Stop_LED_Task();
          DEBUG_printf("\r\n[%d]COM_EXIT\r\n", LED_Index);
          return;
        }
        else if(LED_Stream(LED_Index,1) == COM_BEGIN) {
          if(++LED_Loop_Index >= MAX_NESTED_LOOP) {          // ERROR if over MAX_NESTED_LOOP.
            Stop_LED_Task();
            DEBUG_printf("\r\nCOM_BEGIN_OVER\r\n", LED_Index);
            return;
          }
          DEBUG_printf("\r\n[%d]COM_BEGIN\r\n", LED_Index);
          LED_Loop_Count[LED_Loop_Index] = LED_Stream(LED_Index,2);
          LED_Loop_Begin[LED_Loop_Index] = ++LED_Index;
          DEBUG_printf("LED_Loop_Begin[0]%2d [1]%2d\r\n", LED_Loop_Begin[0], LED_Loop_Begin[1]);
          DEBUG_printf("LED_Loop_Count[0]%2d [1]%2d\r\n", LED_Loop_Count[0], LED_Loop_Count[1]);
          DEBUG_printf("LED_Loop_Index:%2d   LED_Index:%2d\r\n", LED_Loop_Index, LED_Index);
        }
        else if(LED_Stream(LED_Index,1) == COM_END) {
          if(LED_Loop_Index<0) {                             // ERROR if under 0.
            Stop_LED_Task();
            DEBUG_printf("\r\nCOM_END_UNDER\r\n", LED_Index);
            return;
          }
          if(LED_Loop_Count[LED_Loop_Index]>1) {
            DEBUG_printf("\r\n[%d]COM_END-Repeat\r\n", LED_Index);
            if(LED_Loop_Count[LED_Loop_Index]!=0xFF)      LED_Loop_Count[LED_Loop_Index]--;
            LED_Index = LED_Loop_Begin[LED_Loop_Index];       // Jump
            DEBUG_printf("LED_Loop_Begin[0]%2d [1]%2d\r\n", LED_Loop_Begin[0], LED_Loop_Begin[1]);
            DEBUG_printf("LED_Loop_Count[0]%2d [1]%2d\r\n", LED_Loop_Count[0], LED_Loop_Count[1]);
            DEBUG_printf("LED_Loop_Index:%2d   LED_Index:%2d\r\n", LED_Loop_Index, LED_Index);
          }
          else {
            DEBUG_printf("\r\n[%d]COM_END-Next\r\n", LED_Index);
            LED_Loop_Index--;
            LED_Index++;
            DEBUG_printf("LED_Loop_Begin[0]%2d [1]%2d\r\n", LED_Loop_Begin[0], LED_Loop_Begin[1]);
            DEBUG_printf("LED_Loop_Count[0]%2d [1]%2d\r\n", LED_Loop_Count[0], LED_Loop_Count[1]);
            DEBUG_printf("LED_Loop_Index:%2d   LED_Index:%2d\r\n", LED_Loop_Index, LED_Index);
          }
        }
      }
      else {
        int flag_out = 1;
        uint8_t com = LED_Stream(LED_Index,1);
        if(com==0)                flag_out = 0;
        else if(com<=60);         //One/All Pixel Mode
        else if(com< 64)          flag_out = 0;
        else if(com< COM_A_DEC);  //One/All Pixel Buffer Mode
        else if(com<=COM_A_INC) { //One/All Pixel Inc-Dec Mode
          LED_Buffer[0][0] += com-COM_A_HLD;
          DEBUG_printf("[%d]Out All Inc_DecC\r\n", LED_Index);
          for(int i=1; i<LED_PACKET_SIZE; i++) {
            uint8_t d = LED_Stream(LED_Index, i+1);
            if(d < D10)     LED_Buffer[0][i]  = d;
            else            LED_Buffer[0][i] += Inc_Dec[d-D10];
          }
          LED_PutData(LED_Buffer[0]);
          flag_out = 0;
        }
        else if(com<=158);        //Left Pixel Mode
        else if(com<COM_L_DEC)    flag_out = 0;
        else if(com<=COM_L_INC) { //Left Pixel Inc-Dec Mode
          LED_Buffer[1][0] += com-COM_L_HLD;
          DEBUG_printf("[%d]Out Left Inc_DecC\r\n", LED_Index);
          for(int i=1; i<LED_PACKET_SIZE; i++) {
            uint8_t d = LED_Stream(LED_Index, i+1);
            if(d < D10)     LED_Buffer[1][i]  = d;
            else            LED_Buffer[1][i] += Inc_Dec[d-D10];
          }
          LED_PutData(LED_Buffer[1]);
          flag_out = 0;
        }
        else if(com<=222);        //Right Pixel Mode
        else if(com<COM_R_DEC)    flag_out = 0;
        else if(com<=COM_R_INC) { //Right Pixel Inc-Dec Mode
          LED_Buffer[2][0] += com-COM_R_HLD;
          DEBUG_printf("[%d]Out Right Inc_DecC\r\n", LED_Index);
          for(int i=1; i<LED_PACKET_SIZE; i++) {
            uint8_t d = LED_Stream(LED_Index, i+1);
            if(d < D10)     LED_Buffer[2][i]  = d;
            else            LED_Buffer[2][i] += Inc_Dec[d-D10];
          }
          LED_PutData(LED_Buffer[2]);
          flag_out = 0;
        }
        else              flag_out = 0;

        if(flag_out) {
          uint8_t com;
          com = LED_Stream(LED_Index, 1)>>6;
          if(com)       com--;        //com : 0~2

          DEBUG_printf("[%d]Out\r\n", LED_Index);
          for(int i=0; i<LED_PACKET_SIZE; i++) {
            uint8_t d = LED_Stream(LED_Index, i+1);
            if(d < D10)     LED_Buffer[com][i]  = d;
            else            LED_Buffer[com][i] += Inc_Dec[d-D10];
          }
          LED_PutData(LED_Buffer[com]);
        }
        else {
          DEBUG_printf("[%d]No Out\r\n", LED_Index);
        }
        LED_10msec = LED_Stream(LED_Index,0);
        LED_Index++;
      }
    }
  }
}

void Start_LED_Task_Base(uint8_t* led_stream)
{
  if(Flag_LED_Task)     Stop_LED_Task();

  for(int i=0; i<LED_PACKET_SIZE; i++) {
    LED_Buffer[0][i] = 0;
    LED_Buffer[1][i] = 0;
    LED_Buffer[2][i] = 0;
  }

  LED_Stream_ = led_stream;
  LED_Loop_Index = -1;
  LED_Index  = 0;
  LED_10msec = 0;
  Task_Start_10ms(LED_Task);
  Flag_LED_Task = 1;
}

void Stop_LED_Task(void)
{
  if(Flag_LED_Task) {
    Flag_LED_Task = 0;
    Task_Stop_10ms();
  }
}

uint8_t is_Playing_LED_Task(void)
{
  if(Flag_LED_Task)     return HIGH;
  else                  return LOW;
}

#define POSITION_DIFF           (POSITION_MAX-POSITION_MIN)
int check_LvDisplay1,check_LvDisplay2,check_LvDisplay3;   // HSW (24.02.09)
void LED_Display_Level(int8_t  mode, int16_t position_left, int16_t position_right, uint8_t r1, uint8_t g1, uint8_t b1, uint8_t r2, uint8_t g2, uint8_t b2)
{
  static uint8_t led_full = 0;       //Previous
  static uint8_t led_left = 0;       //
  static uint8_t led_right= 0;       //
  uint8_t n;
  uint8_t flag = 0;

  if(mode <= LED_MODE_FULL_LEFT) {     //Full Mode
    check_LvDisplay1++;
    int16_t position = (position_left + position_right)/2;
//    int16_t position = position_left;
//    int16_t position = position_right;
    if(position>=POSITION_MAX)                  n = LED_NUMBER;
    else if(position<=0)                        n = 0;
    else                                        n = (position-POSITION_MIN)*LED_NUMBER/(POSITION_DIFF+1);

    if(led_full != n) {
      led_full = n;
      led_left = led_right = 0;
      if(mode==LED_MODE_FULL_LEFT)              LED_Send_All(n,r1,g1,b1,r2,g2,b2);
      else                                      LED_Send_All(LED_NUMBER-n,r2,g2,b2,r1,g1,b1);
    }
  }
  else {                                //Half Mode
    {
      if(position_left>=POSITION_MAX)           n = LED_HALF_NUMBER;
      else if(position_left<=0)                 n = 0;
      else                                      n = (position_left-POSITION_MIN)*LED_HALF_NUMBER/(POSITION_DIFF+1);

      if(led_left != n) {
        led_left = n;
        led_full = 0;
        if(mode==LED_MODE_HALF_SIDE)            LED_Send_Left(n,r1,g1,b1,r2,g2,b2);
        else                                    LED_Send_Left(LED_HALF_NUMBER-n,r2,g2,b2,r1,g1,b1);
        flag++;
      }
    }
    {
      if(position_right>=POSITION_MAX)          n = LED_HALF_NUMBER;
      else if(position_right<=0)                n = 0;
      else                                      n = (position_right-POSITION_MIN)*LED_HALF_NUMBER/(POSITION_DIFF+1);

      if(led_right != n) {
        led_right = n;
        led_full = 0;
//        if(flag!=0)                             delay_msec(2);    //  HSW
        if(flag!=0)                             delay_msec(4);
        if(mode==LED_MODE_HALF_SIDE)            LED_Send_Right(n,r1,g1,b1,r2,g2,b2);
        else                                    LED_Send_Right(LED_HALF_NUMBER-n,r2,g2,b2,r1,g1,b1);
      }
    }
  }
}

void LED_Blink_ALL(int R, int G, int B, int period_msec) {
  if(period_msec <=10) period_msec = 15;
  for(int i=1; i<LED_NUMBER; i++) {
    LED_Send_Wait(i,R,G,B);
  }
  LED_Send_Now(LED_NUMBER,R,G,B);
  delay_msec(period_msec);
  for(int i=1; i<LED_NUMBER; i++) {
    LED_Send_Wait(i,3,3,3);     //  향후엔 머신 통합 default color로 바꾸기 (파라미터 연동)
  }
  LED_Send_Now(LED_NUMBER,3,3,3);
}

void LED_On_ALL(int R, int G, int B) {
  for(int i=1; i<LED_NUMBER; i++) {
    LED_Send_Wait(i,R,G,B);
  }
  LED_Send_Now(LED_NUMBER,R,G,B);
}

uint8_t status_LED_Welcome=0;
uint8_t cnt_LED_Welcome=0;
void LED_Welcome(void) {
  status_LED_Welcome = 1;
  for(int i=1; i<=LED_NUMBER; i++) {
    LED_Send_Now(i,3,3,51);
    Delay_msec(6);
  }
  for(int i=LED_NUMBER; i>0; i--) {
    LED_Send_Now(i,16,16,102);
    Delay_msec(4);
  }
  for(int i=1; i<=LED_NUMBER; i++) {
    LED_Send_Now(i,29,29,153);
    Delay_msec(5);
  }
  for(int i=LED_NUMBER; i>0; i--) {
    LED_Send_Now(i,42,42,204);
    Delay_msec(4);
  }
  for(int i=1; i<=LED_NUMBER; i++) {
    LED_Send_Now(i,55,55,255);
    Delay_msec(4);
  }
  for(int i=LED_NUMBER; i>0; i--) {
    LED_Send_Now(i,3,3,3);
    Delay_msec(4);
  }
  status_LED_Welcome=0;
  cnt_LED_Welcome++;
  InitialPosCali = 1;
}


/* LED Que 시스템 (250703) -> 쓰레기임. 폐기!!  */
//LED_Queue_Manager led_mgr = {0};
//
//// 초기화
//void LED_Queue_Init(void)
//{
//  led_mgr.write_idx = 0;
//  led_mgr.read_idx = 0;
//  led_mgr.count = 0;
//  led_mgr.busy = 0;
//}
//
//// 큐에 함수 추가
//void LED_Queue_Add(void (*func)(), LED_Policy policy)
//{
//  if(func == NULL) return;
//
//  __disable_irq();
//
//  switch(policy) {
//    case OVERRIDE:
//      // 기존 큐 비우고 맨 앞에 추가 (즉시 실행 X)
//      led_mgr.count = 0;
//      led_mgr.read_idx = led_mgr.write_idx = 0;
//      Stop_LED_Task();  // 현재 실행 중인 것만 중단
//      break;
//
//    case SKIP:
//      // 바쁘면 포기
//      if(led_mgr.busy || is_Playing_LED_Task()) {
//        __enable_irq();
//        return;
//      }
//      break;
//
//    case QUEUE:
//      // 큐가 가득 차면 가장 오래된 것 제거
//      if(led_mgr.count >= LED_QUEUE_SIZE) {
//        led_mgr.read_idx = (led_mgr.read_idx + 1) % LED_QUEUE_SIZE;
//        led_mgr.count--;
//      }
//      break;
//  }
//
//  // 큐에 추가
//  led_mgr.commands[led_mgr.write_idx].func = func;
//  led_mgr.commands[led_mgr.write_idx].policy = policy;
//  led_mgr.write_idx = (led_mgr.write_idx + 1) % LED_QUEUE_SIZE;
//  led_mgr.count++;
//
//  __enable_irq();
//}
//
//// 큐 처리 (스케줄러에서 호출)
//void LED_Queue_Process(void)
//{
//  // 현재 실행 중이면 대기
//  if(led_mgr.busy || is_Playing_LED_Task()) {
//    return;
//  }
//
//  // 큐가 비어있으면 리턴
//  if(led_mgr.count == 0) {
//    return;
//  }
//
//  __disable_irq();
//
//  // 큐에서 명령 꺼내기
//  LED_Command cmd = led_mgr.commands[led_mgr.read_idx];
//  led_mgr.read_idx = (led_mgr.read_idx + 1) % LED_QUEUE_SIZE;
//  led_mgr.count--;
//
//  led_mgr.busy = 1;
//  __enable_irq();
//
//  // 함수 실행
//  if(cmd.func != NULL) {
//    cmd.func();
//  }
//
//  led_mgr.busy = 0;
//}
int cnt_Off = 0;
//void LED_Controller_v2(void){
//
//  // 1순위: 중요한 시스템 상태 (최우선)
//  // 무게 올라가는 중
//  if(WP_LEDCtrl.MotionAutoWeight > 0) {
//    LED_Blink_ALL(5, 50, 50, 20);
//    WP_LEDCtrl.MotionAutoWeight--;
//    return;  // 실행했으면 나머지 스킵
//  }
//  //  BLE 해제
//  if(WP_LEDCtrl.BLEDisconnection > 0){
//    LED_Blink_ALL(80, 20, 5, 20);
//    WP_LEDCtrl.BLEDisconnection--;
//    return;
//  }
//
//  // 웰컴라이트는 기다려주자
//  if(status_LED_Welcome) {
//    return;
//  }
//
//  //  BLE 연결
//  if(WP_LEDCtrl.BLEDisconnection < 0){
//    LED_Blink_ALL(5, 20, 80, 20);
//    WP_LEDCtrl.BLEDisconnection++;
//    return;
//  }
//  // 무게 내려가는 중
//  if (WP_LEDCtrl.MotionAutoWeight < 0) {
//    LED_Blink_ALL(80, 20, 5, 20);
//    WP_LEDCtrl.MotionAutoWeight++;
//    return;
//  }
//
//  // 2순위: 큐 처리 (중간 우선순위)
//  if(led_mgr.count > 0 && !led_mgr.busy && !is_Playing_LED_Task()) {
//    LED_Queue_Process();
//    return;
//  }
//
//  // 3순위: 일반 위치 표시 (낮은 우선순위)
//  if(!led_mgr.busy && !is_Playing_LED_Task()) {
//    if(WP_Weight.Ctrl.OnOffScale[L] >= 1.0f){
//      cnt_Off = 0;
//      LED_Display_Level(LED_MODE_HALF_CENTER, WP_Gym.Position[R], WP_Gym.Position[L], WP_LEDCtrl.R, WP_LEDCtrl.G, WP_LEDCtrl.B, 3, 3, 3);
//    } else if(WP_Weight.Ctrl.OnOffScale[L] <= 0.1f && cnt_Off == 0){
//      for(int i=1; i<LED_NUMBER; i++) {
//        LED_Send_Wait(i,3,3,3);
//      }
//      LED_Send_Now(LED_NUMBER,3,3,3);
//      cnt_Off++;
//    }
//  }
//}


// 임의 위치에서 호출해서 QUEUE에 넣고 싶은 LED 출력 함수는 led.h에서 생성할 것!


/* LED_Controller v1.0.0 코드 백업 */
void LED_Controller(void){

  if(cnt_LED_Welcome < 1) {
    return;
  }
  if(WP_LEDCtrl.MotionAutoWeight > 0) {           //  AutoOn 발동시 +N으로 설정하고 있음 at MotionAutoWeight() in WESPION_App.c
    LED_Blink_ALL(5, 50, 50, 20);
    WP_LEDCtrl.MotionAutoWeight--;
  } else if (WP_LEDCtrl.MotionAutoWeight < 0) {   //  AutoOff 발동시 -N으로 설정하고 있음 at MotionAutoWeight() in WESPION_App.c
    LED_Blink_ALL(80, 20, 5, 20);
    WP_LEDCtrl.MotionAutoWeight++;
  } else {
    if(WP_Weight.Ctrl.OnOffScale[L] >= 1.0f){     // 완전히 On인 경우에만 위치에 수행
      cnt_Off = 0;
      LED_Display_Level(LED_MODE_HALF_CENTER, WP_Gym.Position[R], WP_Gym.Position[L], WP_LEDCtrl.R, WP_LEDCtrl.G, WP_LEDCtrl.B, 3, 3, 3);
      //    LED_Display_Level(LED_MODE_FULL_LEFT, WP_Gym.Position[R], WP_Gym.Position[L], LED_Weight_R, LED_Weight_G, LED_Weight_B, 3, 3, 3);
    } else if(WP_Weight.Ctrl.OnOffScale[L] <= 0.1f && cnt_Off == 0){
      for(int i=1; i<LED_NUMBER; i++) {
        LED_Send_Wait(i,3,3,3);
      }
      LED_Send_Now(LED_NUMBER,3,3,3);
      cnt_Off++;
    }
  }
  //  BLE 해제됨
  if(WP_LEDCtrl.BLEDisconnection>0){
    LED_Blink_ALL(80, 20, 5, 30);
    WP_LEDCtrl.BLEDisconnection--;
  }
  if(status_LED_Welcome) {
    return;
  }
  //  BLE 연결됨
  if(WP_LEDCtrl.BLEDisconnection < 0){
//    LED_Blink_ALL(5, 15, 30, 30);
    LED_Blink_ALL(5, 20, 25, 50);
    WP_LEDCtrl.BLEDisconnection++;
    return;
  }
}
