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

using namespace hw;

/**** 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 ****/
hw::DisplayLed::DisplayLed(bsp::DigitalOut* led0, bsp::DigitalOut* led1, bsp::DigitalOut* led2, bsp::DigitalOut* led3, bsp::DigitalOut* led4, bsp::DigitalOut* led5, bsp::PWMout* common)
{
	this->led0 = led0;
	this->led1 = led1;
	this->led2 = led2;
	this->led3 = led3;
	this->led4 = led4;
	this->led5 = led5;
	this->common = common;
	
	this->led0->write(0);
	this->led1->write(0);
	this->led2->write(0);
	this->led3->write(0);
	this->led4->write(0);
	this->led5->write(0);
	this->common->write(0);
	
	this->lock_counter = 0;
	this->locked = 1;
}

hw::DisplayLed::~DisplayLed(void)
{
	this->led0->write(0);
	this->led1->write(0);
	this->led2->write(0);
	this->led3->write(0);
	this->led4->write(0);
	this->led5->write(0);
	this->common->write(0);
}

void hw::DisplayLed::show_percent(uint8_t percent, style_t style)
{
	uint8_t image = 0x00;
	
	switch(style)
	{
		case LED_DSP_BAR:
		image = img_gen_bar(percent);
		break;
		
		case LED_DSP_DOT10:
		image = img_gen_dot10(percent);
		break;
		
		default:
		image = img_gen_dot20(percent);
		break;
	}
	
	this->write(image);
}

void hw::DisplayLed::write(uint8_t image)
{
	if(image&0x01) this->led0->write(1);
	else this->led0->write(0);
	
	if(image&0x02) this->led1->write(1);
	else this->led1->write(0);
	
	if(image&0x04) this->led2->write(1);
	else this->led2->write(0);
	
	if(image&0x08) this->led3->write(1);
	else this->led3->write(0);
	
	if(image&0x10) this->led4->write(1);
	else this->led4->write(0);
	
	if(image&0x20) this->led5->write(1);
	else this->led5->write(0);
}

void hw::DisplayLed::set_brigthness(uint8_t percent)
{
	this->common->write(percent);
}

void hw::DisplayLed::set_lock(uint16_t timeout)
{
	this->lock_counter = timeout;
	this->locked = 1;
}

void hw::DisplayLed::process_timer(void)
{
	if(this->lock_counter) this->lock_counter--;
	else this->locked = 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;
		
		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;
		
		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;
		
		default:
		return 0x3F;
	}
}