/*
 * sts_lamp_bar.c
 *
 *  Created on: 2022年12月7日
 *      Author: lenovo
 */


#include "main.h"
#include "dma.h"
#include "tim.h"
#include "string.h"
#include "sys_app.h"
#include "sts_lamp_bar.h"

#define ONE_PULSE            				(36)
#define ZERO_PULSE            				(20)

#define LED_DATA_LEN						(24)
#define WS2812B_DATA_LEN					(LED_DATA_LEN * (STS_LAMP_BAR_LED_NUM+4))
#define DEFAULT_LUMINANCE_LEVEL				(20)
#define	RESET_PULSE							(80)

typedef struct {
	uint16_t	head[3];
	uint16_t	GRB[24*STS_LAMP_BAR_LED_NUM];
	uint16_t	tail;
} WS2812B_FrameTypeDef;

volatile WS2812B_FrameTypeDef rgb_buf = {
		.head[0] = 0,
		.head[1] = 0,
		.head[2] = 0,
		.tail 	 = 0
};

uint8_t color_rgb[8][3] = { //STS_COLOR R G B MAPPING TABLE
		{0,0,0},{0,1,0},{1,0,0},{0,0,1},{1,1,0},{1,0,1},{0,1,1},{1,1,1}
};
volatile uint8_t sts_work_mode = STS_DUAL_MODE;
volatile uint8_t sts_reed_hall_ext_int = 0;
volatile uint8_t sts_status_color = STS_DARK;
volatile uint8_t sts_occupancy_status = 0;
volatile uint8_t sts_reed_hall_changed_flag = 1;

uint8_t luminance_level = DEFAULT_LUMINANCE_LEVEL;


void STS_Lamp_Bar_HSV2RGB(uint32_t h, uint32_t s, uint32_t v, uint32_t *r, uint32_t *g, uint32_t *b);


void STS_YunhornSTSEventP1_Process(void)
{
	STS_Reed_Hall_Working();
}

void STS_YunhornSTSEventP2_Process(void)
{

}


void STS_YunhornSTSEventP3_Process(void)
{
	sts_status_color = (STS_Reed_Hall_Status == STS_Status_Open)? STS_GREEN:STS_RED;
	STS_Lamp_Bar_Scoller(sts_status_color, luminance_level);

}

void STS_WS2812B_Set_RGB(uint8_t R, uint8_t G, uint8_t B, uint8_t idx)
{

	if (idx	<	STS_LAMP_BAR_LED_NUM)
	{
		for (uint8_t j = 0;	j <	8;	j ++)
		{
			rgb_buf.GRB[idx*24+j]		=	(G&(0X80)>>j)? ONE_PULSE : ZERO_PULSE;
			rgb_buf.GRB[idx*24+8+j]		=	(R&(0X80)>>j)? ONE_PULSE : ZERO_PULSE;
			rgb_buf.GRB[idx*24+16+j]	=	(B&(0X80)>>j)? ONE_PULSE : ZERO_PULSE;
		}
	}

}
/*
 * COLOR SPACE, H, S, V
 *
 */
void STS_WS2812B_Set_HSV(uint16_t H, uint16_t S, uint16_t V, uint16_t idx)
{
    uint32_t R = 0, G = 0, B = 0;

    if (idx < STS_LAMP_BAR_LED_NUM)
    {
    	STS_Lamp_Bar_HSV2RGB(H, S, V, &R, &G, &B);
    	for (uint16_t i = 0; i < 8; i++)
    	{
    		rgb_buf.GRB[idx*24 + i ]    = (G << i) & (0x80) ? ONE_PULSE : ZERO_PULSE;
    		rgb_buf.GRB[idx*24 + i + 8] = (R << i) & (0x80) ? ONE_PULSE : ZERO_PULSE;
    		rgb_buf.GRB[idx*24 + i +16] = (B << i) & (0x80) ? ONE_PULSE : ZERO_PULSE;
    	}
    }
}

void STS_Lamp_Bar_Full_Color_Gradient(void)
{
    for (uint16_t hue = 0; hue < 360; hue++)
    {
        for (uint8_t i = 0; i < STS_LAMP_BAR_LED_NUM; i++)
        {
        	STS_WS2812B_Set_HSV(hue, DEFAULT_SATURATION, DEFAULT_BRIGHTNESS, i);
        }
        STS_WS2812B_Refresh();
        HAL_Delay(20);
    }
}

/**
 * @brief HSV COLOR SPACE TO RGB COLOR SPACE
 *
 * @param  h HSV   H:Hue, 0~360
 * @param  s HSV   S:Saturation, 0~100
 * @param  v HSV   V:Value of lightness, 0~100
 * @param  r RGB-R
 * @param  g RGB-G
 * @param  b RGB-B
 *
 */
void STS_Lamp_Bar_HSV2RGB(uint32_t h, uint32_t s, uint32_t v, uint32_t *r, uint32_t *g, uint32_t *b)
{
    h %= 360; // h -> [0,360]
    uint32_t rgb_max = v * 2.55f;
    uint32_t rgb_min = rgb_max * (100 - s) / 100.0f;

    uint32_t i = h / 60;
    uint32_t diff = h % 60;

    uint32_t rgb_adj = (rgb_max - rgb_min) * diff / 60;

    switch (i)
    {
    case 0:
        *r = rgb_max;
        *g = rgb_min + rgb_adj;
        *b = rgb_min;
        break;
    case 1:
        *r = rgb_max - rgb_adj;
        *g = rgb_max;
        *b = rgb_min;
        break;
    case 2:
        *r = rgb_min;
        *g = rgb_max;
        *b = rgb_min + rgb_adj;
        break;
    case 3:
        *r = rgb_min;
        *g = rgb_max - rgb_adj;
        *b = rgb_max;
        break;
    case 4:
        *r = rgb_min + rgb_adj;
        *g = rgb_min;
        *b = rgb_max;
        break;
    default:
        *r = rgb_max;
        *g = rgb_min;
        *b = rgb_max - rgb_adj;
        break;
    }
}


void STS_Lamp_Bar_Set_Dark(void)
{
	//APP_LOG(TS_OFF, VLEVEL_M,"\r\n Set Dark .....\r\n");
	HAL_Delay(200);
	for (uint8_t i=0; i< STS_LAMP_BAR_LED_NUM; i++) {

		STS_WS2812B_Set_RGB(0x00,0x00,0x00,i);
	}
	STS_WS2812B_Refresh();
}

void STS_WS2812B_Refresh(void)
{
	HAL_TIM_PWM_Start_DMA(&STS_LAMP_BAR_HTIM, STS_LAMP_BAR_TIM_CHANNEL, (uint32_t *)&rgb_buf, (RESET_PULSE+WS2812B_DATA_LEN));
}


void STS_Lamp_Bar_Init(void)
{
	STS_Lamp_Bar_Set_STS_RGB_Color(STS_GREEN, luminance_level);
	STS_WS2812B_Refresh();
	HAL_Delay(200);
	STS_Lamp_Bar_Set_STS_RGB_Color(STS_RED, luminance_level);
	STS_WS2812B_Refresh();
	HAL_Delay(200);
	STS_Lamp_Bar_Set_STS_RGB_Color(STS_BLUE, luminance_level);
	STS_WS2812B_Refresh();
	HAL_Delay(200);
}

//marquee  scoller
void STS_Lamp_Bar_Scoller(uint8_t color, uint8_t luminance_level)
{
	STS_Lamp_Bar_Set_Dark();
	for(uint8_t i = 0; i<(STS_LAMP_BAR_LED_NUM+1); i++)
	{
		STS_WS2812B_Refresh();
		HAL_Delay(60);
		if (i < STS_LAMP_BAR_LED_NUM) {
			STS_WS2812B_Set_RGB(color_rgb[color][0]*luminance_level,color_rgb[color][1]*luminance_level, color_rgb[color][2]*luminance_level, i);
		}
	}
	STS_WS2812B_Refresh();

}


void STS_Lamp_Bar_Set_RGB_Color(uint8_t red, uint8_t green, uint8_t blue )
{
	HAL_Delay(1);
	for(uint8_t i = 0; i < STS_LAMP_BAR_LED_NUM; i++)
	{
		STS_WS2812B_Set_RGB(red, green, blue, i);
	}
	STS_WS2812B_Refresh();
}

void STS_Lamp_Bar_Set_HSV_Color(uint16_t H, uint16_t S, uint16_t V)
{
	HAL_Delay(1);
	for(uint8_t i = 0; i < STS_LAMP_BAR_LED_NUM; i++)
	{
		STS_WS2812B_Set_HSV(H,	S, V, i);
	}
	STS_WS2812B_Refresh();
}

void STS_Lamp_Bar_Set_STS_RGB_Color(uint8_t sts_lamp_color, uint8_t luminance_level)
{
	uint8_t lum = luminance_level;
	STS_Lamp_Bar_Set_RGB_Color(0x0, 0x0, 0x0);
	switch (sts_lamp_color)
	{
		case STS_DARK:
			STS_Lamp_Bar_Set_RGB_Color(0x0, 0x0, 0x0);
		break;
		case STS_GREEN:
			STS_Lamp_Bar_Set_RGB_Color(0x0, lum, 0x0);
		break;
		case STS_RED:
			STS_Lamp_Bar_Set_RGB_Color(lum, 0x0, 0x0);
		break;
		case STS_BLUE:
			STS_Lamp_Bar_Set_RGB_Color(0x0, 0x0, lum);
		break;
		case STS_YELLOW:
			STS_Lamp_Bar_Set_RGB_Color(lum, lum, 0x0);
		break;
		case STS_PINK:
			STS_Lamp_Bar_Set_RGB_Color(lum, 0x0, lum);
		break;
		case STS_CYAN:
			STS_Lamp_Bar_Set_RGB_Color(0x0, lum, lum);
		break;
		case STS_WHITE:
			STS_Lamp_Bar_Set_RGB_Color(lum, lum, lum);
		break;
		case STS_RED_BLUE:
			STS_Lamp_Bar_Set_RGB_Color(lum, 0x0, 0x0);
			STS_WS2812B_Refresh();
			HAL_Delay(100);
			STS_Lamp_Bar_Set_RGB_Color(0x0, 0x0, lum);
			STS_WS2812B_Refresh();
			HAL_Delay(100);
		break;
	}
}

void STS_Lamp_Bar_Set_STS_HSV_Color(uint8_t sts_lamp_color, uint8_t sts_lamp_hsv_value)
{
	uint8_t hsv_v = sts_lamp_hsv_value;
	uint16_t hsv_s = DEFAULT_SATURATION;

	STS_Lamp_Bar_Set_HSV_Color(0,0,0);

	switch (sts_lamp_color)
	{
		case STS_DARK:
			STS_Lamp_Bar_Set_HSV_Color(0, 0, 0);
		break;
		case STS_GREEN:
			STS_Lamp_Bar_Set_HSV_Color(HSV_GREEN, hsv_s, hsv_v);
		break;
		case STS_RED:
			STS_Lamp_Bar_Set_HSV_Color(HSV_RED, hsv_s, hsv_v);
		break;
		case STS_BLUE:
			STS_Lamp_Bar_Set_HSV_Color(HSV_BLUE, hsv_s, hsv_v);
		break;
		case STS_YELLOW:
			STS_Lamp_Bar_Set_HSV_Color(HSV_YELLOW, hsv_s, hsv_v);
		break;
		case STS_PINK:
			STS_Lamp_Bar_Set_HSV_Color(HSV_PINK, hsv_s, hsv_v);
		break;
		case STS_CYAN:
			STS_Lamp_Bar_Set_HSV_Color(HSV_CYAN, hsv_s, hsv_v);
		break;
		case STS_WHITE:
			STS_Lamp_Bar_Set_HSV_Color(HSV_WHITE, hsv_s, hsv_v);
		break;
		case STS_RED_BLUE:
			STS_Lamp_Bar_Set_HSV_Color(HSV_RED, hsv_s, hsv_v);
			STS_WS2812B_Refresh();
			HAL_Delay(100);
			STS_Lamp_Bar_Set_HSV_Color(HSV_BLUE, hsv_s, hsv_v);
			STS_WS2812B_Refresh();
			HAL_Delay(100);
		break;
	}
}
void STS_Reed_Hall_Working(void)
{

	  if (STS_Reed_Hall_Status == STS_Status_Open) {
		  sts_status_color = STS_GREEN;
		  sts_occupancy_status = 0;

		  APP_LOG(TS_OFF, VLEVEL_M, "\r\n Door Open \r\n");
	  }
	  else if (STS_Reed_Hall_Status == STS_Status_Close) {
		  	sts_occupancy_status = 1;
			sts_status_color = STS_RED;
			APP_LOG(TS_OFF, VLEVEL_M, "\r\n Door Closed \r\n");
	  }

	  STS_Lamp_Bar_Set_STS_RGB_Color(sts_status_color,30);
	  sts_occupancy_status =
	  sts_reed_hall_ext_int = 0;

	switch (sts_work_mode) {
		case STS_NETWORK_MODE:

			break;
		case STS_WIRED_MODE:

			break;
		case STS_REEDSWITCH_MODE:

			break;
		case STS_RSS_MODE:

			break;
		case STS_DUAL_MODE:

				STS_Lamp_Bar_Set_STS_RGB_Color(sts_status_color, luminance_level);

			break;

		case STS_REEDSWITCH:

			break;

		case STS_DUAL_RSS_MODE:

			break;
		case STS_TOF_MODE:

			break;
		case STS_TOF_RSS_MODE:
			break;
		default:
			break;
	}



}

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
	  HAL_TIM_PWM_Stop_DMA(&STS_LAMP_BAR_HTIM,STS_LAMP_BAR_TIM_CHANNEL);
}
void STS_Lamp_Bar_Self_Test(void)
{
	uint8_t color=0, luminance_level=10;

	APP_LOG(TS_OFF, VLEVEL_M, "\r\n YunHorn STS Indicative Lamp Self Test\r\n");

	APP_LOG(TS_OFF, VLEVEL_M, "\r\n [#1] RGB Space Lumianance Level Testing\r\n");
	for (color=STS_GREEN; color <= STS_RED_BLUE; color++)
	{
		luminance_level = 10;
		do {
			STS_Lamp_Bar_Set_STS_RGB_Color(color, luminance_level);
			HAL_Delay(50);
			luminance_level += 10;
		} while (luminance_level < 99);
		STS_Lamp_Bar_Set_Dark();
	}

	HAL_Delay(1000);

	APP_LOG(TS_OFF, VLEVEL_M, "\r\n [#2] Scoller Testing\r\n");
	for (color = STS_GREEN; color <= STS_RED_BLUE; color++)
	{
		STS_Lamp_Bar_Scoller(color, luminance_level);
	}
	STS_Lamp_Bar_Set_Dark();
	HAL_Delay(1000);
/*
	APP_LOG(TS_OFF, VLEVEL_M, "\r\n [#3] HSV space Color Gradient Testing\r\n");
	STS_Lamp_Bar_Full_Color_Gradient();

	APP_LOG(TS_OFF, VLEVEL_M, "\r\n [#4] HSV Space Lumianance Level Testing\r\n");
	uint8_t hsv_value=1;
	for (color=STS_GREEN; color <= STS_RED_BLUE; color++)
	{
		hsv_value = 10;
		do {
			STS_Lamp_Bar_Set_STS_HSV_Color(color, hsv_value);
			HAL_Delay(10);
			hsv_value += 10;
		} while (hsv_value < 99);
		STS_Lamp_Bar_Set_Dark();
	}
*/
	APP_LOG(TS_OFF, VLEVEL_M, "\r\n [##] YunHorn STS Indicative Lamp Self Test Finished\r\n");
	STS_Lamp_Bar_Set_STS_RGB_Color(STS_GREEN, luminance_level);
	HAL_Delay(500);

}
void sts_rgb_unit_test(void)
{

	APP_LOG(TS_OFF, VLEVEL_M, "\r\n STS Lamp Bar Init...\r\n");
	STS_Lamp_Bar_Set_Dark();

	STS_Lamp_Bar_Full_Color_Gradient();

	STS_Lamp_Bar_Self_Test();


}