1428d7b3dSmrgautoload Cairo; 2428d7b3dSmrgimport Cairo; 3428d7b3dSmrglibrary "examples/sort.5c"; 4428d7b3dSmrgimport Sort; 5428d7b3dSmrg 6428d7b3dSmrgint width = 1000, height = 200; 7428d7b3dSmrgint min_vco = 1400000000; 8428d7b3dSmrgint max_vco = 2800000000; 9428d7b3dSmrgint min = 0xffffffff; 10428d7b3dSmrgint max = 0; 11428d7b3dSmrg 12428d7b3dSmrgint max_clocks = 2000; 13428d7b3dSmrgint[4][max_clocks] clocks; 14428d7b3dSmrgint[4][max_clocks] vcos; 15428d7b3dSmrgint[4] clock_count = {0...}; 16428d7b3dSmrg 17428d7b3dSmrgint[4] p2vals = {5,10,7,14}; 18428d7b3dSmrg 19428d7b3dSmrgcairo_t cr = Cairo::new(width, height); 20428d7b3dSmrg 21428d7b3dSmrgvoid calc_p2(int p2i) 22428d7b3dSmrg{ 23428d7b3dSmrg int p2 = p2vals[p2i]; 24428d7b3dSmrg int min_p, max_p; 25428d7b3dSmrg 26428d7b3dSmrg clocks[p2i] = (int [max_clocks]){0...}; 27428d7b3dSmrg 28428d7b3dSmrg if (p2 == 7 || p2 == 14) { 29428d7b3dSmrg /* LVDS */ 30428d7b3dSmrg min_p = 7; 31428d7b3dSmrg max_p = 98; 32428d7b3dSmrg } else { 33428d7b3dSmrg /* SDVO/DAC */ 34428d7b3dSmrg min_p = 5; 35428d7b3dSmrg max_p = 80; 36428d7b3dSmrg } 37428d7b3dSmrg 38428d7b3dSmrg for (int m1 = 10; m1 <= 22; m1++) { 39428d7b3dSmrg for (int m2 = 5; m2 <= 9; m2++) { 40428d7b3dSmrg for (int n = 1; n <= 5; n++) { 41428d7b3dSmrg for (int p1 = 1; p1 <= 8; p1++) { 42428d7b3dSmrg int ref = 96000000; 43428d7b3dSmrg int m = 5 * (m1 + 2) + (m2 + 2); 44428d7b3dSmrg int p = p1 * p2; 45428d7b3dSmrg int vco = floor(ref * m / (n + 2)); 46428d7b3dSmrg int clock = floor(vco / p); 47428d7b3dSmrg 48428d7b3dSmrg if (p < min_p || p > max_p) 49428d7b3dSmrg continue; 50428d7b3dSmrg if (m < 70 || m > 120) 51428d7b3dSmrg continue; 52428d7b3dSmrg if (m2 > m1) 53428d7b3dSmrg continue; /* won't happen */ 54428d7b3dSmrg if (vco < min_vco || vco > max_vco) 55428d7b3dSmrg continue; 56428d7b3dSmrg 57428d7b3dSmrg/* 58428d7b3dSmrg printf("clock: %d (%d,%d), %d, " 59428d7b3dSmrg "(%d,%d)\n", 60428d7b3dSmrg floor(clock / 1000), 61428d7b3dSmrg m1, m2, n, p1, p2); 62428d7b3dSmrg*/ 63428d7b3dSmrg 64428d7b3dSmrg clocks[p2i][clock_count[p2i]] = clock; 65428d7b3dSmrg vcos[p2i][clock_count[p2i]] = vco; 66428d7b3dSmrg clock_count[p2i]++; 67428d7b3dSmrg } 68428d7b3dSmrg } 69428d7b3dSmrg } 70428d7b3dSmrg } 71428d7b3dSmrg} 72428d7b3dSmrg 73428d7b3dSmrgbool sort_p2(poly a, poly b) 74428d7b3dSmrg{ 75428d7b3dSmrg return a > b; 76428d7b3dSmrg} 77428d7b3dSmrg 78428d7b3dSmrgint min_rate = 25000 * 1000; 79428d7b3dSmrgint max_rate = 200000 * 1000; 80428d7b3dSmrg 81428d7b3dSmrgreal scale_x(real clock) 82428d7b3dSmrg{ 83428d7b3dSmrg int min_x = 75, max_x = width - 50; 84428d7b3dSmrg 85428d7b3dSmrg real frac = (clock - min_rate) / (max_rate - min_rate); 86428d7b3dSmrg 87428d7b3dSmrg return min_x + frac * (max_x - min_x); 88428d7b3dSmrg} 89428d7b3dSmrg 90428d7b3dSmrgfor (p2i = 0; p2i < dim(p2vals); p2i++) { 91428d7b3dSmrg int p2 = p2vals[p2i]; 92428d7b3dSmrg calc_p2(p2i); 93428d7b3dSmrg real row_y1 = (p2i + 1) / (dim(p2vals) + 1) * height; 94428d7b3dSmrg real row_y2 = p2i / (dim(p2vals) + 1) * height; 95428d7b3dSmrg 96428d7b3dSmrg /*qsort(&p2vals[p2i], sort_p2);*/ 97428d7b3dSmrg 98428d7b3dSmrg switch (p2) { 99428d7b3dSmrg case 5: 100428d7b3dSmrg set_source_rgb(cr, 1,0,0); 101428d7b3dSmrg break; 102428d7b3dSmrg case 10: 103428d7b3dSmrg set_source_rgb(cr, 0,1,0); 104428d7b3dSmrg break; 105428d7b3dSmrg case 7: 106428d7b3dSmrg set_source_rgb(cr, 0,0,1); 107428d7b3dSmrg break; 108428d7b3dSmrg case 14: 109428d7b3dSmrg set_source_rgb(cr, 0,0,0); 110428d7b3dSmrg break; 111428d7b3dSmrg } 112428d7b3dSmrg 113428d7b3dSmrg /* draw the line for the clock */ 114428d7b3dSmrg for (int i = 0; i < clock_count[p2i]; i++) { 115428d7b3dSmrg int clock = clocks[p2i][i]; 116428d7b3dSmrg real xpos; 117428d7b3dSmrg 118428d7b3dSmrg if (clock < min_rate || clock > max_rate) 119428d7b3dSmrg continue; 120428d7b3dSmrg 121428d7b3dSmrg xpos = scale_x(clock); 122428d7b3dSmrg move_to(cr, xpos, row_y1); 123428d7b3dSmrg line_to(cr, xpos, row_y2); 124428d7b3dSmrg stroke(cr); 125428d7b3dSmrg } 126428d7b3dSmrg 127428d7b3dSmrg set_source_rgb(cr, 1, 1, 1); 128428d7b3dSmrg /* add a mark for the vco value of the clocks at each location */ 129428d7b3dSmrg for (int i = 0; i < clock_count[p2i]; i++) { 130428d7b3dSmrg int clock = clocks[p2i][i]; 131428d7b3dSmrg int vco = vcos[p2i][i]; 132428d7b3dSmrg real mark_center; 133428d7b3dSmrg 134428d7b3dSmrg if (clock < min_rate || clock > max_rate) 135428d7b3dSmrg continue; 136428d7b3dSmrg 137428d7b3dSmrg real xpos = scale_x(clock); 138428d7b3dSmrg real vcofrac = (vco - min_vco) / (max_vco - min_vco); 139428d7b3dSmrg real mark_height = (row_y1 + vcofrac * (row_y2 - row_y1)); 140428d7b3dSmrg 141428d7b3dSmrg move_to(cr, xpos, mark_height - 1); 142428d7b3dSmrg line_to(cr, xpos, mark_height + 1); 143428d7b3dSmrg stroke(cr); 144428d7b3dSmrg } 145428d7b3dSmrg 146428d7b3dSmrg set_source_rgb(cr, 0, 0, 0); 147428d7b3dSmrg string p2label = sprintf("p2 = %d", p2); 148428d7b3dSmrg move_to(cr, 5, (p2i + .5) / (dim(p2vals) + 1) * height + 4); 149428d7b3dSmrg show_text(cr, p2label); 150428d7b3dSmrg} 151428d7b3dSmrg 152428d7b3dSmrgvoid label_clock(real clock) { 153428d7b3dSmrg real center_x = scale_x(clock); 154428d7b3dSmrg string label = sprintf("%d", floor((clock + 500) / 1000000)); 155428d7b3dSmrg text_extents_t e = text_extents(cr, label); 156428d7b3dSmrg real left_x = center_x - e.x_advance / 2; 157428d7b3dSmrg save(cr); 158428d7b3dSmrg move_to(cr, left_x, height - 20); 159428d7b3dSmrg show_text(cr, label); 160428d7b3dSmrg restore(cr); 161428d7b3dSmrg} 162428d7b3dSmrg 163428d7b3dSmrglabel_clock(min_rate); 164428d7b3dSmrglabel_clock(max_rate); 165428d7b3dSmrglabel_clock(140 * 1000 * 1000); 166428d7b3dSmrglabel_clock(115 * 1000 * 1000); 167428d7b3dSmrglabel_clock(100 * 1000 * 1000); 168428d7b3dSmrglabel_clock(82 * 1000 * 1000); 169428d7b3dSmrg 170428d7b3dSmrgstring xlabel = "Clock in Mhz"; 171428d7b3dSmrgtext_extents_t e = text_extents(cr, xlabel); 172428d7b3dSmrgmove_to(cr, width / 2 - e.x_advance / 2, height - 5); 173428d7b3dSmrgshow_text(cr, xlabel); 174428d7b3dSmrgsleep(10); 175