/**** Includes ****/
#include "../utils/utils.h"
#include "display.h"

using namespace dccd;

/**** Private definitions ****/
/**** Private constants ****/
/**** Private variables ****/
/**** Private function declarations ****/
static uint8_t img_gen_dot10(uint8_t percent);
static uint8_t img_gen_dot20(uint8_t percent);
static uint8_t img_gen_bar(uint8_t percent);

/**** Public function definitions ****/
dccd::DccdDisplay::DccdDisplay(void)
{
	return;
}

dccd::DccdDisplay::~DccdDisplay(void)
{
	return;
}

void dccd::DccdDisplay::init(dccd::DccdHw* dccd_hw)
{	
	this->hardware = dccd_hw;
	this->brigth_pwm = 50;
	this->dimm_pwm = 25;
	
	this->next_image = 0x00;
	this->next_lock_lvl = 0;
	this->next_lock_time = 0;
	this->act_image = 0x00;
	this->act_lock_lvl = 0;
}

void dccd::DccdDisplay::cfg_debounce(uint16_t dbnc_time)
{
	this->hardware->dimm.dbnc_lim = dbnc_time;
}

void dccd::DccdDisplay::write(uint8_t image, uint8_t lock_lvl, uint16_t lock_time)
{
	if(lock_lvl < this->next_lock_lvl) return;
	
	this->next_image = image;
	this->next_lock_lvl = lock_lvl;
	this->next_lock_time = lock_time;
}

void dccd::DccdDisplay::write_percent(uint8_t percent, uint8_t style, uint8_t lock_lvl, uint16_t lock_time)
{
	uint8_t img = 0x01;
	
	switch(style)
	{
		case 1:
		img = img_gen_dot20(percent);
		break;
		
		case 2:
		img = img_gen_bar(percent);
		break;
		
		default:
		img = img_gen_dot10(percent);
		break;
	}
	
	this->write(img, lock_lvl, lock_time);
}

void dccd::DccdDisplay::force_backlight(uint8_t percent)
{
	if(percent > this->brigth_pwm) percent = this->brigth_pwm;
	this->hardware->display.write_backlight(percent);
}

void dccd::DccdDisplay::process(void)
{	
	// Process DIMM switch
	if(this->hardware->dimm.is_new)
	{
		this->hardware->dimm.is_new = 0;
		if(this->hardware->dimm.state) this->hardware->display.write_backlight(this->dimm_pwm);
		else this->hardware->display.write_backlight(this->brigth_pwm);
	};
	
	// Image processor
	uint8_t update_img = 0;
	if(this->next_lock_lvl >= this->act_lock_lvl) update_img = 1;
	else if(this->hardware->display.is_cycle_end()) update_img = 1;
	
	if(update_img)
	{
		this->act_image = this->next_image;
		this->act_lock_lvl = this->next_lock_lvl;
		
		if(this->next_lock_time > 0)
		{
			this->hardware->display.write(this->act_image, this->next_lock_time, this->next_lock_time, 1);
		}
		else
		{
			this->hardware->display.write(this->act_image);
			this->act_lock_lvl = 0;
		}
	};
}

/**** Private function definitions ***/
static uint8_t img_gen_dot10(uint8_t percent)
{
	switch(percent)
	{
		case 0 ... 5:
		return 0x01;
		
		case 6 ... 15:
		return 0x03;
		
		case 16 ... 25:
		return 0x02;
		
		case 26 ... 35:
		return 0x06;
		
		case 36 ... 45:
		return 0x04;
		
		case 46 ... 55:
		return 0x0C;
		
		case 56 ... 65:
		return 0x08;
		
		case 66 ... 75:
		return 0x18;
		
		case 76 ... 85:
		return 0x10;
		
		case 86 ... 95:
		return 0x30;
		
		case 96 ... 100:
		return 0x20;
		
		default:
		return 0x20;
	}
}

static uint8_t img_gen_dot20(uint8_t percent)
{
	switch(percent)
	{
		case 0 ... 10:
		return 0x01;
		
		case 11 ... 30:
		return 0x02;
		
		case 31 ... 50:
		return 0x04;
		
		case 51 ... 70:
		return 0x08;
		
		case 71 ... 90:
		return 0x10;
		
		case 91 ... 100:
		return 0x20;
		
		default:
		return 0x20;
	}
}

static uint8_t img_gen_bar(uint8_t percent)
{
	switch(percent)
	{
		case 0 ... 10:
		return 0x01;
		
		case 11 ... 30:
		return 0x03;
		
		case 31 ... 50:
		return 0x07;
		
		case 51 ... 70:
		return 0x0F;
		
		case 71 ... 90:
		return 0x1F;
		
		case 91 ... 100:
		return 0x3F;
		
		default:
		return 0x3F;
	}
}