• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Supports CVT 1.2 reduced blanking modes v1 and v2
2 
3 #include <kms++/kms++.h>
4 #include <cmath>
5 
6 using namespace std;
7 
8 namespace kms
9 {
10 static float CELL_GRAN = 8;
11 static float CELL_GRAN_RND = round(CELL_GRAN);
12 
13 struct CVTConsts {
14 	float CLOCK_STEP;
15 	float MIN_V_BPORCH;
16 	float RB_H_BLANK;
17 	float RB_H_FPORCH;
18 	float RB_H_SYNC;
19 	float RB_H_BPORCH;
20 	float RB_MIN_V_BLANK;
21 	float RB_V_FPORCH;
22 	float REFRESH_MULTIPLIER;
23 };
24 
25 static const CVTConsts cvt_consts_v1 = {
26 	.CLOCK_STEP = 0.25, // Fixed
27 	.MIN_V_BPORCH = 6, // Min
28 	.RB_H_BLANK = 160, // Fixed
29 	.RB_H_FPORCH = 48, // Fixed
30 	.RB_H_SYNC = 32, // Fixed
31 	.RB_H_BPORCH = 80, // Fixed
32 	.RB_MIN_V_BLANK = 460, // Min
33 	.RB_V_FPORCH = 3, // Fixed
34 	.REFRESH_MULTIPLIER = 1, // Fixed
35 };
36 
37 static const CVTConsts cvt_consts_v2 = {
38 	.CLOCK_STEP = 0.001, // Fixed
39 	.MIN_V_BPORCH = 6, // Fixed
40 	.RB_H_BLANK = 80, // Fixed
41 	.RB_H_FPORCH = 8, // Fixed
42 	.RB_H_SYNC = 32, // Fixed
43 	.RB_H_BPORCH = 40, // Fixed
44 	.RB_MIN_V_BLANK = 460, // Min
45 	.RB_V_FPORCH = 1, // Min
46 	.REFRESH_MULTIPLIER = 1, // or 1000/1001
47 };
48 
videomode_from_cvt(uint32_t hact,uint32_t vact,uint32_t refresh,bool ilace,bool reduced_v2,bool video_optimized)49 Videomode videomode_from_cvt(uint32_t hact, uint32_t vact, uint32_t refresh, bool ilace, bool reduced_v2, bool video_optimized)
50 {
51 	CVTConsts c = reduced_v2 ? cvt_consts_v2 : cvt_consts_v1;
52 
53 	if (video_optimized)
54 		c.REFRESH_MULTIPLIER = 1000.0 / 1001.0;
55 
56 	bool INT_RQD = ilace;
57 
58 	float H_PIXELS = hact;
59 	float V_LINES = vact;
60 	float IP_FREQ_RQD = refresh ? refresh : 60;
61 	if (ilace)
62 		IP_FREQ_RQD /= 2;
63 
64 	float V_SYNC_RND;
65 
66 	if (reduced_v2) {
67 		V_SYNC_RND = 8;
68 	} else {
69 		if (hact * 3 == vact * 4)
70 			V_SYNC_RND = 4;
71 		else if (hact * 9 == vact * 16)
72 			V_SYNC_RND = 5;
73 		else if (hact * 10 == vact * 16)
74 			V_SYNC_RND = 6;
75 		else if (hact == 1280 && (vact == 1024 || vact == 768))
76 			V_SYNC_RND = 7;
77 		else
78 			V_SYNC_RND = 10;
79 	}
80 
81 	// 5.2.1
82 	float V_FIELD_RATE_RQD = INT_RQD ? IP_FREQ_RQD * 2 : IP_FREQ_RQD;
83 
84 	// 5.2.2
85 	float H_PIXELS_RND = floor(H_PIXELS / CELL_GRAN_RND) * CELL_GRAN_RND;
86 
87 	// 5.2.3
88 	float LEFT_MARGIN = 0;
89 	float RIGHT_MARGIN = 0;
90 
91 	// 5.2.4
92 	float TOTAL_ACTIVE_PIXELS = H_PIXELS_RND + LEFT_MARGIN + RIGHT_MARGIN;
93 
94 	// 5.2.5
95 	float V_LINES_RND = INT_RQD ? floor(V_LINES / 2) : floor(V_LINES);
96 
97 	// 5.2.6
98 	float TOP_MARGIN = 0;
99 	float BOT_MARGIN = 0;
100 
101 	// 5.2.7
102 	float INTERLACE = INT_RQD ? 0.5 : 0;
103 
104 	// 5.4.8
105 	float H_PERIOD_EST = ((1000000 / V_FIELD_RATE_RQD) - c.RB_MIN_V_BLANK) / (V_LINES_RND + TOP_MARGIN + BOT_MARGIN);
106 
107 	// 5.4.9
108 	float VBI_LINES = floor(c.RB_MIN_V_BLANK / H_PERIOD_EST) + 1;
109 
110 	// 5.4.10
111 	float RB_MIN_VBI = c.RB_V_FPORCH + V_SYNC_RND + c.MIN_V_BPORCH;
112 	float ACT_VBI_LINES = VBI_LINES < RB_MIN_VBI ? RB_MIN_VBI : VBI_LINES;
113 
114 	// 5.4.11
115 	float TOTAL_V_LINES = ACT_VBI_LINES + V_LINES_RND + TOP_MARGIN + BOT_MARGIN + INTERLACE;
116 
117 	// 5.4.12
118 	float TOTAL_PIXELS = c.RB_H_BLANK + TOTAL_ACTIVE_PIXELS;
119 
120 	// 5.4.13
121 	float ACT_PIXEL_FREQ = c.CLOCK_STEP * floor((V_FIELD_RATE_RQD * TOTAL_V_LINES * TOTAL_PIXELS / 1000000 * c.REFRESH_MULTIPLIER) / c.CLOCK_STEP);
122 
123 	// 5.4.14
124 	//float ACT_H_FREQ = 1000 * ACT_PIXEL_FREQ / TOTAL_PIXELS;
125 
126 	// 5.4.15
127 	//float ACT_FIELD_RATE = 1000 * ACT_H_FREQ / TOTAL_V_LINES;
128 
129 	// 5.4.16
130 	//float ACT_FRAME_RATE = INT_RQD ? ACT_FIELD_RATE / 2 : ACT_FIELD_RATE;
131 
132 	// 3.4.3.7 Adjust vfp
133 	if (reduced_v2)
134 		c.RB_V_FPORCH = ACT_VBI_LINES - V_SYNC_RND - c.MIN_V_BPORCH;
135 
136 	Videomode mode;
137 
138 	mode = videomode_from_timings(ACT_PIXEL_FREQ * 1000,
139 				      H_PIXELS_RND, c.RB_H_FPORCH, c.RB_H_SYNC, c.RB_H_BPORCH,
140 				      V_LINES_RND * (INT_RQD ? 2 : 1), c.RB_V_FPORCH, V_SYNC_RND, ACT_VBI_LINES - V_SYNC_RND - c.RB_V_FPORCH);
141 
142 	mode.set_hsync(SyncPolarity::Positive);
143 	mode.set_vsync(SyncPolarity::Negative);
144 
145 	mode.set_interlace(INT_RQD);
146 
147 	return mode;
148 }
149 
150 } // namespace kms
151