/*
 * Core1_LED_Control.c
 *
 * Created: Wed Jan 12 2022 15:29:18
 *  Author Chris
 */
// ============================================================================================
// Includes
#include "Core1_LED_Control.h"

#include "pico/stdlib.h"

#include "PWM.h"
#include "EEPROM_M24C64.h"


// ============================================================================================
// Defines
#define GPIO_CHANNEL_1_R		1
#define GPIO_CHANNEL_1_G		3
#define GPIO_CHANNEL_1_B		2


// ============================================================================================
// Variables
static volatile struct repeating_timer 	_Timer_Core1_LED_Control;
static volatile bool					_Timer_Fired;

uint8_t _Current_Duty_Cylces[NUM_LED_CHANNELS][NUM_LED_COLORS];
uint8_t _Target_Duty_Cylces[NUM_LED_CHANNELS][NUM_LED_COLORS];
uint8_t _Fade_Speed[NUM_LED_CHANNELS];

static const uint8_t _Channel_Color_PWM_LUT[NUM_LED_CHANNELS][NUM_LED_COLORS] = 
{
	[LED_Channel_1] = {
		[R] = GPIO_CHANNEL_1_R,
		[G] = GPIO_CHANNEL_1_G,
		[B] = GPIO_CHANNEL_1_B
	}
};

static bool _Use_Gamma_Correction = false;

const uint8_t _DutyCycle_Gamma_Correction_LUT[] = {
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   1,   1,   1,
    1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,   2,   2,
    2,   3,   3,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   5,   5,   5,
    5,   6,   6,   6,   6,   7,   7,   7,   7,   8,   8,   8,   9,   9,   9,  10,
   10,  10,  11,  11,  11,  12,  12,  13,  13,  13,  14,  14,  15,  15,  16,  16,
   17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,  22,  23,  24,  24,  25,
   25,  26,  27,  27,  28,  29,  29,  30,  31,  32,  32,  33,  34,  35,  35,  36,
   37,  38,  39,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  50,
   51,  52,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  66,  67,  68,
   69,  70,  72,  73,  74,  75,  77,  78,  79,  81,  82,  83,  85,  86,  87,  89,
   90,  92,  93,  95,  96,  98,  99, 101, 102, 104, 105, 107, 109, 110, 112, 114,
  115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142,
  144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175,
  177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213,
  215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255 };

// ============================================================================================
// Function Declarations
uint8_t Core1_LED_Control_Get_DC_Corrected(uint8_t dc_index);


/*******************************************************************
	Interrupt Service Routines
*******************************************************************/
bool ISR_Repeating_Timer_Core1_LED_Control(struct repeating_timer *t)
{
	_Timer_Fired = true;
	
	for(uint ch=LED_Channel_1;ch<NUM_LED_CHANNELS;ch++)
	{
		for(uint co=Red;co<=Blue;co++)
		{
			uint8_t New;
			uint8_t Current = _Current_Duty_Cylces[ch][co];
			uint8_t Target 	= _Target_Duty_Cylces[ch][co];

			if(Current > Target)
			{
				if((Current - Target) <= _Fade_Speed[ch]) {
					New = Target;
				} else {
					New = Current - _Fade_Speed[ch];
				}
			}
			else if(Current < Target)
			{
				if((Target - Current) <= _Fade_Speed[ch]) {
					New = Target;
				} else {
					New = Current + _Fade_Speed[ch];
				}
			}
			else
			{
				continue;
			}

			Core1_LED_Control_Set_DC_Direct(ch, co, New);
		}
	}

    return true;
}


/*******************************************************************
	Functions
*******************************************************************/
void Core1_LED_Control_Init(void)
{
	_Timer_Fired = false;
	
	for(uint ch=LED_Channel_1;ch<NUM_LED_CHANNELS;ch++)
	{
		for(uint co=Red;co<NUM_LED_COLORS;co++)
		{
			PWM_Init_GPIO		(_Channel_Color_PWM_LUT[ch][co], true, PWM_CLOCK_DEFAULT);
			PWM_Set_Top_Value	(_Channel_Color_PWM_LUT[ch][co], UINT8_MAX);
			
			Core1_LED_Control_Set_DC_Direct(ch, co, 0);
			Core1_LED_Control_Set_DC_Target(ch, co, 0);
		}
		Core1_LED_Control_Set_Fade_Speed(ch, 1);
	}

	add_repeating_timer_ms(TIMER_INTERVALL_LED_UPDATE_ms, &ISR_Repeating_Timer_Core1_LED_Control, NULL, (struct repeating_timer *)&_Timer_Core1_LED_Control);
}

bool Core1_LED_Control_Get_Timer_Fired(void)
{
	bool Return_Value = _Timer_Fired;

	_Timer_Fired = false;

	return Return_Value;
}

void Core1_LED_Control_Set_DC_Direct(enum LED_Channel channel, enum LED_Color color, uint8_t duty_cycle)
{
	if(channel >= NUM_LED_CHANNELS || color >= NUM_LED_COLORS) {
		return;
	}

	PWM_Set_Duty_Cycle(_Channel_Color_PWM_LUT[channel][color], Core1_LED_Control_Get_DC_Corrected(duty_cycle));

	_Current_Duty_Cylces[channel][color] = duty_cycle;
}

void Core1_LED_Control_Set_DC_Target(enum LED_Channel channel, enum LED_Color color, uint8_t duty_cycle)
{
	if(channel >= NUM_LED_CHANNELS || color >= NUM_LED_COLORS) {
		return;
	}

	_Target_Duty_Cylces[channel][color] = duty_cycle;
}

uint8_t Core1_LED_Control_Get_DC(enum LED_Channel channel, enum LED_Color color)
{
	if(channel >= NUM_LED_CHANNELS || color >= NUM_LED_COLORS) {
		return 0;
	}

	return  _Current_Duty_Cylces[channel][color];
}

void Core1_LED_Control_Set_Fade_Speed(enum LED_Channel channel, uint8_t fade_speed)
{
	if(channel >= NUM_LED_CHANNELS) {
		return;
	}

	_Fade_Speed[channel] = fade_speed;
}	

void Core1_LED_Control_Set_Use_Color_Correction(bool use_color_correction)
{
	_Use_Gamma_Correction = use_color_correction;
}


/*******************************************************************
	Internal Functions
*******************************************************************/
uint8_t Core1_LED_Control_Get_DC_Corrected(uint8_t dc_index)
{
	if(_Use_Gamma_Correction) {
		return _DutyCycle_Gamma_Correction_LUT[dc_index];
	}

	return dc_index;
}