/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    yunhorn_sts_lamp_bar.c											   *
  * @author  Yunhorn (r) Technology Limited Application Team	               *
  * @brief   Yunhorn (r) SmarToilets (r) Product configuration file.		   *
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 Yunhorn Technology Limited.
  * Copyright (c) 2022 Shenzhen Yunhorn Technology Co., Ltd.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
#include "main.h"
#include "dma.h"
#include "tim.h"
#include "string.h"
#include "sys_app.h"
#include "stm32_systime.h"
#include "sts_lamp_bar.h"

#include "yunhorn_sts_sensors.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							(10)  //(80)  TO FIX DARK_COLOR AND SM2


typedef struct ws2812b_e {
	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}
};
extern volatile uint8_t sts_service_mask;
extern volatile uint8_t sts_work_mode;
volatile uint8_t sts_reed_hall_ext_int = 0;
volatile uint8_t sts_status_color = STS_GREEN;
volatile uint8_t sts_lamp_bar_color = STS_GREEN;		//puColor
volatile uint8_t sts_cloud_netcolor = STS_GREEN;		//netColor
extern volatile uint8_t sts_occupancy_status;

extern volatile uint8_t sts_reed_hall_result, sts_emergency_button_pushed;	// inital 0 = close
volatile uint8_t sts_hall1_read=STS_Status_Door_Open,sts_hall2_read=STS_Status_SOS_Release; // Above hall1_read == reed_hall_result, hall2_read == emergency_button
extern volatile uint8_t sts_reed_hall_1_result, sts_reed_hall_2_result;
extern volatile uint8_t sts_tof_result_changed_flag;


extern volatile uint8_t sts_reed_hall_1_changed_flag, sts_reed_hall_2_changed_flag;
extern volatile uint8_t sts_rss_result_changed_flag, sts_hall_1_changed_flag, sts_hall_2_changed_flag, sts_reed_hall_changed_flag;
extern volatile uint8_t sts_rss_result;
extern volatile uint8_t sts_rss_2nd_result;		//2nd RSS sensor status
extern volatile uint8_t sts_tof_result;
#ifdef 	STS_M1
extern volatile uint8_t sts_water_leakage_changed_flag;
#endif
//extern volatile uint8_t last_sts_reed_hall_result = 2;   //Initial state, not 0, not 1
volatile uint8_t last_lamp_bar_color=STS_GREEN;
extern volatile uint8_t sts_presence_fall_detection;
extern volatile uint8_t sts_fall_rising_detected_result;
extern volatile float sts_presence_rss_distance;
extern volatile uint8_t sensor_data_ready;
extern SysTime_t mems_event_time;
extern volatile uint32_t event_start_time, event_stop_time;
extern volatile uint32_t event_door_lock_start_time, event_door_lock_stop_time;
uint8_t luminance_level = DEFAULT_LUMINANCE_LEVEL;






void STS_Lamp_Bar_Set_Dark(void)
{
	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+1));

	//HAL_TIM_PWM_Start_IT(&STS_LAMP_BAR_HTIM, STS_LAMP_BAR_TIM_CHANNEL);
}

void STS_Lamp_Bar_Init(void)
{
	if (sts_service_mask == STS_SERVICE_MASK_L0)
	{
		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++)
	{
		//if (sts_service_mask < STS_SERVICE_MASK_L1)
		//	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);
		}
	}
	HAL_Delay(10);

	//if (sts_service_mask == STS_SERVICE_MASK_L0) {
	//	STS_WS2812B_Refresh();
	//}

}


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;
		}
	}
	// CHANGED AT 2023-05-10
	if (sts_service_mask == STS_SERVICE_MASK_L0) {
		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++)
	{
		for (uint8_t j = 0;	j <	8;	j ++)
		{
			rgb_buf.GRB[i*24+j]			=	(green&(0x80)>>j)? ONE_PULSE : ZERO_PULSE;
			rgb_buf.GRB[i*24+8+j]		=	(red&(0x80)>>j)? ONE_PULSE : ZERO_PULSE;
			rgb_buf.GRB[i*24+16+j]		=	(blue&(0x80)>>j)? ONE_PULSE : ZERO_PULSE;
		}
	}
	if (sts_service_mask == STS_SERVICE_MASK_L0) {
		STS_WS2812B_Refresh();
	}

}


void STS_Lamp_Bar_Refresh(void)
{
	STS_Lamp_Bar_Set_STS_RGB_Color(sts_lamp_bar_color, luminance_level);
}
void STS_Lamp_Bar_Set_STS_RGB_Color(uint8_t sts_lamp_color, uint8_t luminance_level)
{
	uint8_t lum = luminance_level;
	static bool r_b = false;
	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:
			if (r_b)
				STS_Lamp_Bar_Set_RGB_Color(lum, 0x0, 0x0);
			else
				STS_Lamp_Bar_Set_RGB_Color(0x0, 0x0, lum);
			r_b = !r_b;
		break;
	}
}

void STS_Reed_Hall_Working(void)
{

}
void STS_Combined_Status_Processing(void)
{
	mems_event_time = SysTimeGetMcuTime();

	if ((sts_rss_result == STS_RESULT_MOTION) || (sts_reed_hall_1_result == STS_Status_Door_Close)|| (sts_reed_hall_2_result == STS_Status_SOS_Pushdown) || (sts_tof_result == STS_RESULT_PRESENCE))
	{

		if (event_start_time == 0) {

			event_start_time = mems_event_time.Seconds;
			event_door_lock_start_time = event_start_time;
			event_stop_time = 0;

			APP_LOG(TS_OFF, VLEVEL_H, "\r\n Event Started at %6u Seconds \r\n", event_start_time);
		}


	} else	if ((sts_rss_result != STS_RESULT_MOTION) || (sts_reed_hall_1_result != STS_Status_Door_Close)|| (sts_reed_hall_2_result != STS_Status_SOS_Pushdown)  || (sts_tof_result != STS_RESULT_PRESENCE))
	{
		if (event_stop_time ==0)
		{
			event_stop_time = mems_event_time.Seconds;
			event_door_lock_stop_time = event_stop_time;
			event_start_time = 0;

			APP_LOG(TS_OFF, VLEVEL_H, "\r\n Event Stop at %6u Seconds, Duration = %6u Seconds\r\n", event_stop_time, (event_stop_time-event_start_time));
		}
	}

	switch (sts_work_mode)
	{
		case STS_NETWORK_MODE:
			sts_status_color = sts_cloud_netcolor;
			break;
		case STS_WIRED_MODE:				// NO LAMP BAR FOR THOSE WATER LEAKAGE SENSOR OR SOAP CAPACITY SENSORS
			sts_status_color = STS_DARK;
#ifdef 	STS_M1
			sts_water_leakage_result = (sts_reed_hall_result == STS_Status_Door_Open )?STS_RESULT_WATER_LEAKAGE_YES:STS_RESULT_WATER_LEAKAGE_NO;
			sts_water_leakage_changed_flag = 1;
#endif
			break;
		case STS_REEDSWITCH_MODE:

			sts_status_color = (sts_reed_hall_result == STS_Status_Door_Open )? STS_GREEN: STS_RED;

			break;
		case STS_RSS_MODE:
			if (sts_rss_result == STS_RESULT_NO_MOTION){
				sts_status_color = STS_GREEN;
			} else if ((sts_rss_result == STS_RESULT_MOTION))
			{
				sts_status_color = STS_RED;
			}
			break;
		case STS_DUAL_MODE:
			uint8_t flapping_flag=0;
			if ((event_stop_time - event_start_time)<=4) {
				flapping_flag=1;
			}
			if (!flapping_flag) {

			if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_reed_hall_1_result == STS_Status_Door_Open )&& (sts_reed_hall_2_result == STS_Status_SOS_Release ))
			{
				sts_status_color = STS_GREEN;

			} else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_reed_hall_1_result == STS_Status_Door_Close )||(sts_reed_hall_2_result == STS_Status_SOS_Pushdown ))
			{
				sts_status_color = STS_RED;
				if (sts_fall_rising_detected_result == STS_PRESENCE_LAYDOWN) {
					sts_lamp_bar_color = STS_YELLOW;
					sts_status_color = STS_YELLOW;
				} else if (sts_fall_rising_detected_result == STS_PRESENCE_FALL){		//RED_BLUE FLASH
					sts_lamp_bar_color = STS_RED_BLUE;
					sts_status_color = STS_RED_BLUE;
				} else if (sts_fall_rising_detected_result == STS_PRESENCE_RISING) {  //NORMAL OCCUPANCY STATUS
					sts_lamp_bar_color = STS_RED;
					sts_status_color = STS_RED;
				}
				if (sts_reed_hall_2_result == STS_Status_SOS_Pushdown )
				{
					sts_status_color = STS_RED_BLUE;
				}
			}
			}

			break;
		case STS_REMOTE_REED_RSS_MODE:
			if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_reed_hall_result == STS_Status_Door_Open ))
			{
				sts_status_color = STS_GREEN;

			} else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_reed_hall_result == STS_Status_Door_Close ))
			{
				sts_status_color = STS_RED;
			}
			break;
		case STS_DUAL_RSS_MODE:
			if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_rss_2nd_result == STS_RESULT_NO_MOTION))
			{
				sts_status_color = STS_GREEN;
			} else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_rss_2nd_result == STS_RESULT_MOTION))
			{
				sts_status_color = STS_RED;
			}

			break;
		case STS_TOF_RSS_MODE:
			if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_tof_result == STS_RESULT_NO_PRESENCE)){
				sts_status_color = STS_GREEN;

			} else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_tof_result == STS_RESULT_PRESENCE))
			{
				sts_status_color = STS_RED;
			}

			break;
//   TO-DO LIST  ***********************************************************
		case STS_TOF_DISTANCE_MODE:
			if ((sts_tof_result == STS_RESULT_NO_PRESENCE)) {
				sts_status_color = STS_GREEN;
			} else if ((sts_tof_result == STS_RESULT_PRESENCE)) {
				sts_status_color = STS_RED;
			}
			break;
		case STS_TOF_PRESENCE_MODE:
			if ((sts_tof_result == STS_RESULT_NO_PRESENCE)) {
				sts_status_color = STS_GREEN;
			} else if ((sts_tof_result == STS_RESULT_PRESENCE)) {
				sts_status_color = STS_RED;
			}
			break;
		case STS_TOF_IN_OUT_MODE:
			if ((sts_tof_result == STS_RESULT_NO_PRESENCE)) {
				sts_status_color = STS_GREEN;
			} else if ((sts_tof_result == STS_RESULT_PRESENCE)) {
				sts_status_color = STS_RED;
			}
			break;
//   TO-DO LIST  ***********************************************************
		default:
			break;
	}

#if 0
	if (sts_status_color == STS_RED_BLUE)
	{
		//STS_Lamp_Bar_Set_STS_RGB_Color(sts_lamp_bar_color, luminance_level);
		STS_Lamp_Bar_Set_STS_RGB_Color(STS_RED, luminance_level);
		HAL_Delay(100);
		STS_Lamp_Bar_Set_STS_RGB_Color(STS_BLUE, luminance_level);
		HAL_Delay(100);
		STS_Lamp_Bar_Set_STS_RGB_Color(STS_RED_BLUE, luminance_level);
	}
#endif
	if ((sts_work_mode == STS_WIRED_MODE) || (sts_service_mask > STS_SERVICE_MASK_L0))
	{
		sts_status_color = STS_DARK;
		sts_lamp_bar_color = STS_DARK;
		last_lamp_bar_color = STS_DARK;
		STS_Lamp_Bar_Set_Dark();
	}
	else
	{

		//if ((last_lamp_bar_color != sts_status_color))
		{
			sts_lamp_bar_color = ((sts_service_mask == STS_SERVICE_MASK_L0)? sts_status_color:STS_DARK);

				STS_Lamp_Bar_Set_STS_RGB_Color(sts_lamp_bar_color, luminance_level);

				if ((sts_service_mask == STS_SERVICE_MASK_L0) || (sts_lamp_bar_color == STS_DARK))
				{
				//	STS_WS2812B_Refresh();
				}

			last_lamp_bar_color = sts_lamp_bar_color;
		}
	}

	STS_Lamp_Bar_Refresh();
#if 1
	if ((sts_rss_result_changed_flag)|| (sts_reed_hall_1_changed_flag)|| (sts_reed_hall_2_changed_flag) || (sts_tof_result_changed_flag) )
		//|| (sts_water_leakage_changed_flag))
	{

		//sts_rss_result_changed_flag =0;
		sts_rss_result_changed_flag =0;
		sts_reed_hall_1_changed_flag =0;
		sts_reed_hall_2_changed_flag =0;
		sts_tof_result_changed_flag =0;
#ifdef 	STS_M1
		sts_water_leakage_changed_flag=0;
#endif
		sensor_data_ready = 1;
		//STS_PRESENCE_SENSOR_Prepare_Send_Data();
	}
#endif
}

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
	  __HAL_TIM_SetCompare(&STS_LAMP_BAR_HTIM, STS_LAMP_BAR_TIM_CHANNEL,0);
	  HAL_TIM_PWM_Stop_DMA(&STS_LAMP_BAR_HTIM,STS_LAMP_BAR_TIM_CHANNEL);

}

void STS_Lamp_Bar_Self_Test_Simple(void)
{
	uint8_t color=0, luminance_level=10;
	APP_LOG(TS_OFF, VLEVEL_M, "\r\n [#1] RGB Space Lumianance Level Testing Start\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 += 20;
		} while (luminance_level < 99);
		//STS_Lamp_Bar_Set_Dark();
	}
	APP_LOG(TS_OFF, VLEVEL_M, "\r\n [#1] RGB Space Lumianance Level Testing Finished\r\n");
}
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");

	STS_Lamp_Bar_Self_Test_Simple();

	APP_LOG(TS_OFF, VLEVEL_H, "\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();

	APP_LOG(TS_OFF, VLEVEL_M, "\r\n [##] YunHorn STS Indicative Lamp Self Test Finished\r\n");
	if ((sts_work_mode == STS_WIRED_MODE) )
	{
		STS_Lamp_Bar_Set_Dark();
	} else
	{
		STS_Lamp_Bar_Set_STS_RGB_Color(STS_GREEN, luminance_level);
	}


}
void sts_rgb_unit_test(void)
{

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

	STS_Lamp_Bar_Set_Dark();

	STS_Lamp_Bar_Full_Color_Gradient();

	STS_Lamp_Bar_Self_Test();

	do {
		for (uint8_t i=0; i<9; i++)
		{
			APP_LOG(TS_OFF, VLEVEL_L, "\r\n STS Lamp Bar color = %d...\r\n", i);

			STS_Lamp_Bar_Set_STS_RGB_Color(i, luminance_level);
			STS_Combined_Status_Processing();
			HAL_Delay(6000);
			STS_Lamp_Bar_Set_Dark();
		}
	} while(1);



}