
#include <stdio.h>

#include "floatstr_t.h"

// Class FloatStr
void FloatStr::Init(float In_Value, float In_Min_Value, float In_Max_Value, float In_StepSize, int In_AfterDot, int In_MaxLength, char In_Text[20], char In_PreText[10], char In_Unit[5])
{
	//set protected attributes
	Value        = In_Value;
	Stored_Value = In_Value;
	Min_Value    = In_Min_Value;
	Max_Value    = In_Max_Value;
	StepSize     = In_StepSize;
	AfterDot     = In_AfterDot;
	MaxLength    = In_MaxLength;
	
	sprintf(Text, "%s", In_Text);
	
	sprintf(PreText, "%s", In_PreText);
	
	sprintf(Unit, "%s", In_Unit);
	
	sprintf(DimensionUnit, "");
	
	RenderText();
	
}

float FloatStr::Read_Value(void)
{
	return Value;
}

int FloatStr::Read_IntBDot(void)
{
	return Value_BDot;
}

int FloatStr::Read_IntADot(void)
{
	return Value_ADot;
}

void FloatStr::Write_Value(float In_Value)
{
	Value = In_Value;
}

float FloatStr::Read_Stored_Value(void)
{
	return Stored_Value;
}

void FloatStr::Write_Stored_Value(float In_Stored_Value)
{
	Stored_Value = In_Stored_Value;
}

float FloatStr::Read_Min_Value(void)
{
	return Min_Value;
}

void FloatStr::Write_Min_Value(float In_Min_Value)
{
	Min_Value = In_Min_Value;
}

float FloatStr::Read_Max_Value(void)
{
	return Max_Value;
}

void FloatStr::Write_Max_Value(float In_Max_Value)
{
	Max_Value = In_Max_Value;
}

float FloatStr::Read_StepSize(void)
{
	return StepSize;
}

void FloatStr::Write_StepSize(float In_StepSize)
{
	StepSize = In_StepSize;
}

int FloatStr::Read_AfterDot(void)
{
	return AfterDot;
}

void FloatStr::Write_AfterDot(int In_AfterDot)
{
	AfterDot = In_AfterDot;
}

int FloatStr::Read_MaxLength(void)
{
	return MaxLength;
}

void FloatStr::Write_MaxLength(int In_MaxLength)
{
	MaxLength = In_MaxLength;
}
//##########################################################################################################################################################
// BF several bugs fixed.
// Values are printed with after dot positions now. Fixed overflow and underrun and cleaned up
// the variable declarations in this routine.

void FloatStr::RenderText(void)
{
	
	char           Calc_AfterDot = AfterDot;
	volatile float Calc_Value    = Value;
	
	float floatad = 0;
	int   intbd   = 0;				//integer value before dot
	int   intad   = 0;				//integer value after dot

	if (Calc_Value == 0)
	{
		sprintf(Text, "%s 0.0 %s", PreText, Unit);
		return;
	}	
	else if (Calc_Value > 0)
	{
		Calc_Value += (Calc_Value*0.0005);	//round up to avoid round errors

		if (Calc_Value > 1)
		{ DimensionUnit[0] = ' '; }	

		// exponents 10^-3 / 10^-6 / 10^-9
		if (Calc_Value < 1)
		{
			Calc_Value *= 1000;
			DimensionUnit[0] = 'm';
		}
		if (Calc_Value < 1)
		{
			Calc_Value *= 1000;
			DimensionUnit[0] = '&';	
		}
		if (Calc_Value < 1)
		{
			Calc_Value *= 1000;
			DimensionUnit[0] = 'n';	
		}
		if (Calc_Value < 1)
		{
			Calc_Value *= 1000;
			DimensionUnit[0] = 'p';	
		}				
		if (Calc_Value < 1)			//Value is too small -> zero
		{
			Calc_Value = 0;
			DimensionUnit[0] = ' ';	
		}


		// exponents 10^3 / 10^6 / 10^9
		if (Calc_Value >= 1000)
		{
			//Calc_Value /= 1000;
			Calc_Value *= 0.001;
			DimensionUnit[0] = 'k';
		}
		if (Calc_Value >= 1000)
		{
			//Calc_Value /= 1000;
			Calc_Value *= 0.001;
			DimensionUnit[0] = 'M';
		}
		if (Calc_Value >= 1000)
		{
			//Calc_Value /= 1000;
			Calc_Value *= 0.001;
			DimensionUnit[0] = 'G';
		}
		if (Calc_Value >= 1000)			//Value is too big -> infinite
		{
			sprintf(Text, "%s *** %s", PreText, Unit);
			return;
		}

	}
	else if (Calc_Value < 0)
	{
		Calc_Value += (Calc_Value*0.0005);	//round up to avoid round errors

		if (Calc_Value < -1)
		{ DimensionUnit[0] = ' '; }

		// exponents 10^-3 / 10^-6 / 10^-9
		if (Calc_Value > -1)
		{
			Calc_Value *= 1000;
			DimensionUnit[0] = 'm';
		}
		if (Calc_Value > -1)
		{
			Calc_Value *= 1000;
			DimensionUnit[0] = '&';	
		}
		if (Calc_Value > -1)
		{
			Calc_Value *= 1000;
			DimensionUnit[0] = 'n';	
		}
		if (Calc_Value > -1)
		{
			Calc_Value *= 1000;
			DimensionUnit[0] = 'p';	
		}				
		if (Calc_Value > -1)			//Value is too small -> zero
		{
			Calc_Value = 0;
			DimensionUnit[0] = ' ';	
		}


		// exponents 10^3 / 10^6 / 10^9
		if (Calc_Value <= -1000)
		{
			//Calc_Value /= 1000;
			Calc_Value *= 0.001;
			DimensionUnit[0] = 'k';
		}
		if (Calc_Value <= -1000)
		{
			//Calc_Value /= 1000;
			Calc_Value *= 0.001;
			DimensionUnit[0] = 'M';
		}
		if (Calc_Value <= -1000)
		{
			//Calc_Value /= 1000;
			Calc_Value *= 0.001;
			DimensionUnit[0] = 'G';
		}
		if (Calc_Value >= 1000)			//Value is too big -> infinite
		{
			sprintf(Text, "%s *** %s", PreText, Unit);
			return;
		}
	}
/*
	//round up to avoid round errors
	if (Calc_Value > 0)
	Calc_Value += 0.0005;
	else if (Calc_Value < 0)
	Calc_Value -= 0.0005;
*/

	// Copy Float to Integer
	intbd = (int)Calc_Value;			//get before dot integer
		
	//check how many after dot positions are possible depending on maximum print length
	if (intbd > 0)
	{	
		if (intbd < 10)
		{
			if ((AfterDot + 1) > MaxLength) Calc_AfterDot = MaxLength - 1;
		}
		else if (intbd < 100)
		{
			if ((AfterDot + 2) > MaxLength) Calc_AfterDot = MaxLength - 2;
		}
		else
		{
			if ((AfterDot + 3) > MaxLength) Calc_AfterDot = MaxLength - 3;
		}
	}
	else
	{	
		if (intbd > -10)
		{
			if ((AfterDot + 1) > MaxLength) Calc_AfterDot = MaxLength - 1;
		}
		else if (intbd > -100)
		{
			if ((AfterDot + 2) > MaxLength) Calc_AfterDot = MaxLength - 2;
		}
		else
		{
			if ((AfterDot + 3) > MaxLength) Calc_AfterDot = MaxLength - 3;
		}
	}
		

	floatad = Calc_Value - (float)intbd; 		//get after dot value as float - cut off before dot
	
	//convert after dot to integer (with 1-4 positions)
	switch(Calc_AfterDot)
	{	
		case 0: intad = (int)floatad; break;
		case 1: intad = (int)(floatad * 10); break;
		case 2: intad = (int)(floatad * 100); break;
		case 3: intad = (int)(floatad * 1000); break;
		case 4: intad = (int)(floatad * 10000); break;
	}

	if(intad < 0)
	{ intad *= -1 ;}				//we don't need negative values after dot


	//copy values to text string depending on positions after dot
	switch(Calc_AfterDot)
	{
		//case 0: sprintf(Text, "%s%3d.0 %s%s", PreText, intbd, DimensionUnit, Unit); break;
		case 0: sprintf(Text, "%s%3d %s%s", PreText, intbd, DimensionUnit, Unit); break;
		case 1: sprintf(Text, "%s%3d.%01d %s%s", PreText, intbd, intad, DimensionUnit, Unit); break;
		case 2: sprintf(Text, "%s%3d.%02d %s%s", PreText, intbd, intad, DimensionUnit, Unit); break;
		case 3: sprintf(Text, "%s%3d.%03d %s%s", PreText, intbd, intad, DimensionUnit, Unit); break;
		case 4: sprintf(Text, "%s%3d.%04d %s%s", PreText, intbd, intad, DimensionUnit, Unit); break;
	}  
	
	// copy values to protected variables for readout via Read_Int(B/A)Dot()
	Value_BDot = intbd;
	Value_ADot = intad;

}
//#####################################################################################################################################
char* FloatStr::Read_Text(void)
{
	return(&Text[0]);
}

char* FloatStr::Read_PreText(void)
{
	return(&PreText[0]);
}

void FloatStr::Write_PreText(char In_PreText[10])
{
	sprintf(PreText, "%s", In_PreText);
}

char* FloatStr::Read_Unit(void)
{
	return(&Unit[0]);
}

void FloatStr::Write_Unit(char In_Unit[5])
{
	sprintf(Unit, "%s", In_Unit);
}

char* FloatStr::Read_DimensionUnit(void)
{
	return(&DimensionUnit[0]);
}

void FloatStr::DoStep(char Direction)
{
	float Calc_Value = Value;
/*	
	if (Calc_Value < 0.000001) StepSize = 0.000000005;
	else
	{
		StepSize = 0.01;
		while (Calc_Value < 1)
		{
			Calc_Value = Calc_Value * 10;
			StepSize = StepSize / 10;
		}
	}
*/	
	if (Direction == 1)
	 { if (Value < Max_Value) Value = Value + StepSize; }
	else
	 { if (Value > Min_Value) Value = Value - StepSize; }
}

