
// ****************************************************************************
//
//                         Page PH - pulse histogram
//
// ****************************************************************************

#include "../include.h"

#define PH_SAMPNUM	112			// number of samples (border 2*8 pixels)
#define PH_BUF_L	((u32*)Buf)		// pointer to LOW sample buffer
#define PH_BUF_H	((u32*)Buf + 128)	// pointer to HIGH sample buffer

#define PH_HIST_H	20			// height of one histogram

u16 PH_Last;		// time of last edge
Bool PH_NewSet;		// counter to delete a few first samples

/* Timer base: 2 us
0: 0x0000 order 0, value 0, 0 s

1: 0x0001 order 1, value 1, 2 us

2: 0x0002 order 2+0, value 2, 4 us
3: 0x0003 order 2+1, value 3, 6 us .... 5 us

4: 0x0004 order 3+0, value 4, 8 us
5: 0x0005 order 3+1, value 5, 10 us ...... 10 us
6: 0x0006 order 3+2, value 6, 12 us
7: 0x0007 order 3+3, value 7, 14 us
// dif 1 (0 bits cut out)
8: 0x0008 order 4+0, value 8, 16 us
9: 0x0009 order 4+1, value 9, 18 us
10: 0x000A order 4+2, value 10, 20 us
11: 0x000B order 4+3, value 11, 22 us
12: 0x000C order 4+4, value 12, 24 us
13: 0x000D order 4+5, value 13, 26 us
14: 0x000E order 4+6, value 14, 28 us
15: 0x000F order 4+7, value 15, 30 us
// dif 2 (1 bit cut out)
16: 0x0010-0x0011 order 5+0, value 16-17, 32-34 us
17: 0x0012-0x0013 order 5+1, value 18-19, 36-38 us
18: 0x0014-0x0015 order 5+2, value 20-21, 40-42 us
19: 0x0016-0x0017 order 5+3, value 22-23, 44-46 us
20: 0x0018-0x0019 order 5+4, value 24-25, 48-50 us ... 50 us
21: 0x001A-0x001B order 5+5, value 26-27, 52-54 us
22: 0x001C-0x001D order 5+6, value 28-29, 56-58 us
23: 0x001E-0x001F order 5+7, value 30-31, 60-62 us
// dif 4 (2 bits cut out)
24: 0x0020-0x0023 order 6+0, value 32-35, 64-70 us
25: 0x0024-0x0027 order 6+1, value 36-39, 72-78 us
26: 0x0028-0x002B order 6+2, value 40-43, 80-86 us
27: 0x002C-0x002F order 6+3, value 44-47, 88-94 us
28: 0x0030-0x0033 order 6+4, value 48-51, 96-102 us ... 100 us
29: 0x0034-0x0037 order 6+5, value 52-55, 104-110 us
30: 0x0038-0x003B order 6+6, value 56-59, 112-118 us
31: 0x003C-0x003F order 6+7, value 60-63, 120-123 us
// dif 8 (3 bits cut out)
32: 0x0040-0x0047 order 7+0, value 64-71, 124-142 us
33: 0x0048-0x004F order 7+1, value 72-79, 144-158 us
34: 0x0050-0x0057 order 7+2, value 80-87, 160-174 us
35: 0x0058-0x005F order 7+3, value 88-95, 176-190 us
36: 0x0060-0x0067 order 7+4, value 96-103, 192-206 us
37: 0x0068-0x006F order 7+5, value 104-111, 208-222 us
38: 0x0070-0x0077 order 7+6, value 112-119, 224-238 us
39: 0x0078-0x007F order 7+7, value 120-127, 240-254 us
// dif 16 (4 bits cut out)
40: 0x0080-0x008F order 8+0, value 128-143, 256-286 us
41: 0x0090-0x009F order 8+1, value 144-159, 288-318 us
42: 0x00A0-0x00AF order 8+2, value 160-175, 320-350 us
43: 0x00B0-0x00BF order 8+3, value 176-191, 352-382 us
44: 0x00C0-0x00CF order 8+4, value 192-207, 384-414 us
45: 0x00D0-0x00DF order 8+5, value 208-223, 416-446 us
46: 0x00E0-0x00EF order 8+6, value 224-239, 448-478 us
47: 0x00F0-0x00FF order 8+7, value 240-255, 480-510 us ... 500us
// dif 32 (5 bits cut out)
48: 0x0100-0x011F order 9+0, value 256-287, 512-574 us
49: 0x0120-0x013F order 9+1, value 288-319, 576-638 us
50: 0x0140-0x015F order 9+2, value 320-351, 630-702 us
51: 0x0160-0x017F order 9+3, value 352-383, 704-766 us
52: 0x0180-0x019F order 9+4, value 384-415, 768-830 us
53: 0x01A0-0x01BF order 9+5, value 416-447, 832-894 us
54: 0x01C0-0x01DF order 9+6, value 448-479, 896-958 us
55: 0x01E0-0x01FF order 9+7, value 480-511, 960-1022 us ... 1 ms
// dif 64 (6 bits cut out)
56-63: 0x0200-0x03FF order 10+0..7, value 512-1023, 1024-2046 us
// dif 128 (7 bits cut out)
64-71: 0x0400-0x07FF order 11+0..7, value 1024-2047, 2048-4094 us
// dif 256 (8 bits cut out)
72-79: 0x0800-0x0FFF order 12+0..7, value 2048-4095, 4096-8190 us
  73: 0x0900-0x9FF order 12+1, value 2304-2559, 4608-5118 ... 5ms
// dif 512 (9 bits cut out)
80-87: 0x1000-0x1FFF order 13+0..7, value 4096-8191, 8192-16382 us
  81: 0x1200-0x13FF order 13+1, value 4068-5119, 8136-10238 us .... 10 ms
// dif 1024 (10 bits cut out)
88-95: 0x2000-0x3FFF order 14+0..7, value 8192-16383, 16384-32766 us
// dif 2048 (11 bits cut out)
96-103: 0x4000-0x7FFF order 15+0..7, value 16384-32767, 32768-65535 us
  100: 0x6000-0x67FF order 15+4, value 24576-26623, 49152-53246 us .. 50 ms
// dif 4096 (12 bits cut out)
104-111: 0x8000-0xFFFF order 16+0..7, value 32768-65535, 65536-131070 us
  104: 0x8000
  105: 0x9000
  106: 0xA000
  107: 0xB000
  108: 0xC000-0xCFFF order 16+4, value 49152-53247, 98304-106494 us .... 100 ms
*/

/*
// interrupt on signal edge ... handler located at page_asm.S
//HANDLER void NOFLASH(TIM1_CC_IRQHandler)()
HANDLER void NOFLASH(PH_Handler)()
{
	// read capture result
	u16 t = TIM1_GetComp1();

	// clear interrupt request
	TIM1_CC1IntClr();

	// get difference from previous edge
	u16 t2 = (u16)(t - PH_Last);
	PH_Last = t;	// save time of new edge

	// get sample index
	int inx;
	if (t2 < 16)
		inx = t2;
	else
	{
		// get sample order (first value 16: ord = 32 - 27 = 5)
		int ord = 32 - clz(t2);

		// get index (starting with index 16, 8 values per order)
		inx = ((ord - 5) << 3) + 16;
		inx += (t2 >> (ord - 4)) & 7; // add linear 3-bit part
	}

	// falling edge - end of HIGH pulse
	if ((TIM1->CCER & B1) != 0)
	{
		// select rising edge
		TIM1_IC1Rise();

		// count HIGH pulse
		PH_BUF_H[inx]++;
	}

	// rising edge - end of LOW pulse
	else
	{
		// select falling edge
		TIM1_IC1Fall();

		// count LOW pulse
		PH_BUF_L[inx]++;
	}
}
*/

// PH reset
void PH_Reset()
{
	int i;
	for (i = 0; i < PH_SAMPNUM; i++) PH_BUF_L[i] = 0;
	for (i = 0; i < PH_SAMPNUM; i++) PH_BUF_H[i] = 0;
}

// PH initialize
void PH_Init()
{
	// PH reset
	PH_Reset();
	PH_NewSet = True; // delete a few first samples

	// DUT initialize
	DUT_Init(True);
}

// PH terminate
void PH_Term()
{
	// DUT terminate (shared with PH and REP pages; IN_GPIO stays in IN_PD mode)
	DUT_Term();

	// reset input pin
	GPIO_PinReset(IN_GPIO);
}

// PH display one histogram
// total height: 20 lines
//  17 lines data
//  1 line base
//  2 lines marks
void PH_Disp1(u32* buf, int y)
{
	// loop samples ... skip value 0
	int inx;
	for (inx = 0; inx < PH_SAMPNUM; inx++)
	{
		// get sample
		u32 s = buf[inx];

		// get order 0..32
		u32 ord = 32 - clz(s);

		// height of line 0..16
		int h = ord >> 1;

		// draw line
		DrawVLineSet(inx + 8, y + 17 - h, h);
	}

	// draw base line
	DrawHLineSet(8, y+17, PH_SAMPNUM-1);

	// draw marks
	y += 18;
	DrawPointSet(8+5, y);	// 10us
	DrawPointSet(8+28, y);	// 100us
	DrawPointSet(8+55, y);	// 1ms
	DrawPointSet(8+81, y);	// 10ms
	DrawPointSet(8+108, y);	// 100ms

	DrawPointSet(8+3, y);	// 5us
	DrawPointSet(8+20, y);	// 50us
	DrawPointSet(8+47, y);	// 500us
	DrawPointSet(8+73, y);	// 5ms
	DrawPointSet(8+100, y);	// 50ms

	y++;
	DrawPointSet(8+5, y);	// 10us
	DrawPointSet(8+28, y);	// 100us
	DrawPointSet(8+55, y);	// 1ms
	DrawPointSet(8+81, y);	// 10ms
	DrawPointSet(8+108, y);	// 100ms
}

// PH display
void PH_Disp()
{
	// clear area
	DrawRectClrFast(0, TITLE_H, WIDTH, HEIGHT-TITLE_H);

	// select font 8x12
	SelFont12();

	// delete a few first samples
	if (PH_NewSet)
	{
		int inx;
		u32 sum = 0;
		for (inx = 0; inx < PH_SAMPNUM; inx++) sum += PH_BUF_H[inx];
		if (sum > 3)
		{
			PH_Reset();
			PH_NewSet = False;
		}
	}

	// display histograms
	PH_Disp1(PH_BUF_H, TITLE_H);
	PH_Disp1(PH_BUF_L, TITLE_H+PH_HIST_H);

	// draw scale
	SelFont8();
	DrawText("10", 8+5-8, HEIGHT-8);
	DrawText("100", 8+28-12, HEIGHT-8);
	DrawText("1", 8+55-4, HEIGHT-8);
	DrawText("10", 8+81-8, HEIGHT-8);
	DrawText("100", 8+108-12, HEIGHT-8);

	// display update
	DispUpdate();
}

// Page PH (returns key PREV/NEXT)
u8 PagePH()
{
	u8 key;
	int i;

	// PH initialize
	PH_Init();

	// PH display
	PH_Disp();

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

		// PH display
		PH_Disp();

		// get keys
		key = KeyGet();
		switch (key)
		{
		// Prev
		case KEY_PREV:
		// Next
		case KEY_NEXT:
			// PH terminate
			PH_Term();
			return key;

		// Hold
		case KEY_HOLD:
			// reset
			PH_Reset();
			break;
		}
	}
}
