
// ****************************************************************************
//
//                          Page I - current meter
//
// ****************************************************************************

#include "../include.h"

s32 IState;		// I current in mA
s32 ITare = 0;		// I current tare in mA

// I update (takes 500ms)
// ADC clock divider is set to 750kHz. One ADC clock cycle is 1.3us.
// I sampling time is (6) 71.5 cycles. One sample is 71.5+12.5=84 ADC clock cycles = 112us.
// 4464 samples take approx. 4464*112=500ms.
// The measurement period is 500 ms – this is so that the measurement period is an integer
// multiple of the electrical distribution period, i.e., Europe 20 ms (50 Hz), USA 16.7 ms
// (60 Hz). This ensures greater resistance to noise from the electrical distribution network.
void I_Update()
{
	int n;
	u32 i, t;
	u8 key;

	// Select channel to be converted and discard first few samples.
	// With a short sample time, the voltage in the sampling capacitors
	// needs to stabilize.
	ADC1_GetSingleMul(I_ADC, 10);

	// measure I current
	n = 0;		// sample counter
	i = 0;		// sample accumulator (max. value 4464*4095 = 18M, OK for u32)
	cb();
	t = Time();	// start time
	cb();
	while ((u32)(Time() - t) < 500000*HCLK_PER_US)
	{
		// software start conversion
		ADC1_SwStart();

		// wait end of conversion
		while (!ADC1_EndGet()) {}

		// get conversion result (and clear "end of conversion" flag)
		i += ADC1_Data() & 0xfff;

		// sample counter
		n++;

		// break from keyboard
		key = KeyBuf;
		if ((key == KEY_PREV) || (key == KEY_NEXT)) break;
	}

	// get current in mA (val = i * Supply * I_K / (n * 4095 * (1<<12))
	s64 k1 = (s64)(u64)i * Supply * I_K;
	s64 k2 = ((s64)(u64)n * 4095 * (1<<I_SHIFT));
	int val = (int)((k1 + (k2>>1))/k2);

	// tare
	IState = val - ITare;
}

// I initialize (initializes BAT measure, too)
void I_Init()
{
	// BAT initialize, initialize ADC single conversion mode, set ADC clock to 750kHz
	BAT_Init();

	// setup input pins
	GPIO_Mode(I_GPIO, GPIO_MODE_AIN);	// I GPIO

	// set sampling time of I input ADC to 71.5 cycles
	ADC1_SampTime(I_ADC, 6);		// I input ADC channel

	// clear measure
	IState = 0;
}

// I terminate (terminates BAT measure, too)
void I_Term()
{
	// BAT terminate
	BAT_Term();

	// reset input pins
	GPIO_PinReset(I_GPIO);	// I GPIO
}

// I display tare ("tare 12mA")
void I_DispTare()
{
	// select font
	SelFont12();

	// clear row
	DrawRectClrFast(0, ROW4_Y, WIDTH, FONTH);

	// draw title
	int x = (WIDTH-9*8)/2;
	DrawText("tare", x, ROW4_Y);
	x += 5*8;

	// current tare
	char* s = DecNumBuf;
	int len = DecNum(s, ITare, 0);
	DrawText(s, x, ROW4_Y);
	x += len*8;
	DrawText("mA", x, ROW4_Y);
}

// I display
void I_Disp()
{
	// display values
	UI_DispVal(IState, ROW2_Y, 'A');

	// display tare correction
	I_DispTare();

	// display update
	DispUpdate();
}

// I tare
void I_Tare()
{
	TareMsg();
	ITare = IState + ITare;
	I_DispTare();
	DispUpdate();
	WaitMs(500);
}

// Page I (returns key PREV/NEXT)
u8 PageI()
{
	int i;
	u8 key;

	// I initialize (initializes BAT measure, too)
	I_Init();

	// I display
	I_Disp();

	while (True)
	{
		// reload watchdog counter
		IWDG_Reload();

		// update battery supply voltage (takes 100ms)
		BAT_Update();

		// I update (takes 500ms)
		I_Update();

		// I display
		I_Disp();

		// keyboard input
		key = KeyGet();
		switch (key)
		{
		// change page
		case KEY_PREV:
		case KEY_NEXT:
			// I terminate (terminates BAT measure, too)
			I_Term();
			return key;

		// Hold - tare
		case KEY_HOLD:
			I_Tare();
			break;
		}
	}
}
