1 #include "footprint_generator_grid.hpp"
2 #include "widgets/pool_browser_button.hpp"
3 #include "document/idocument_package.hpp"
4 #include "pool/ipool.hpp"
5 #include "pool/package.hpp"
6 
7 namespace horizon {
FootprintGeneratorGrid(IDocumentPackage & c)8 FootprintGeneratorGrid::FootprintGeneratorGrid(IDocumentPackage &c)
9     : Glib::ObjectBase(typeid(FootprintGeneratorGrid)),
10       FootprintGeneratorBase("/org/horizon-eda/horizon/imp/footprint_generator/grid.svg", c)
11 {
12     update_preview();
13 
14     sp_pitch_h = Gtk::manage(new SpinButtonDim());
15     sp_pitch_h->set_range(0, 50_mm);
16     sp_pitch_h->set_valign(Gtk::ALIGN_CENTER);
17     sp_pitch_h->set_halign(Gtk::ALIGN_END);
18     sp_pitch_h->set_value(3_mm);
19     overlay->add_at_sub(*sp_pitch_h, "#pitch_h");
20     sp_pitch_h->show();
21 
22     sp_pitch_v = Gtk::manage(new SpinButtonDim());
23     sp_pitch_v->set_range(0, 50_mm);
24     sp_pitch_v->set_valign(Gtk::ALIGN_CENTER);
25     sp_pitch_v->set_halign(Gtk::ALIGN_START);
26     sp_pitch_v->set_value(3_mm);
27     sp_pitch_v->signal_value_changed().connect(sigc::mem_fun(*this, &FootprintGeneratorGrid::update_xy_lock));
28     overlay->add_at_sub(*sp_pitch_v, "#pitch_v");
29     sp_pitch_v->show();
30 
31     sp_pad_height = Gtk::manage(new SpinButtonDim());
32     sp_pad_height->set_range(0, 50_mm);
33     sp_pad_height->set_valign(Gtk::ALIGN_CENTER);
34     sp_pad_height->set_halign(Gtk::ALIGN_START);
35     sp_pad_height->set_value(.5_mm);
36     sp_pad_height->signal_value_changed().connect(sigc::mem_fun(*this, &FootprintGeneratorGrid::update_xy_lock));
37     overlay->add_at_sub(*sp_pad_height, "#pad_height");
38     sp_pad_height->show();
39 
40     sp_pad_width = Gtk::manage(new SpinButtonDim());
41     sp_pad_width->set_range(0, 50_mm);
42     sp_pad_width->set_valign(Gtk::ALIGN_CENTER);
43     sp_pad_width->set_halign(Gtk::ALIGN_START);
44     sp_pad_width->set_value(.5_mm);
45     overlay->add_at_sub(*sp_pad_width, "#pad_width");
46     sp_pad_width->show();
47 
48     {
49         auto tbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 4));
50         auto la = Gtk::manage(new Gtk::Label("Count H:"));
51         tbox->pack_start(*la, false, false, 0);
52 
53         sp_count_h = Gtk::manage(new Gtk::SpinButton());
54         sp_count_h->set_range(4, 512);
55         sp_count_h->set_increments(1, 1);
56         tbox->pack_start(*sp_count_h, false, false, 0);
57 
58         box_top->pack_start(*tbox, false, false, 0);
59     }
60     {
61         auto tbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 4));
62         auto la = Gtk::manage(new Gtk::Label("Count V:"));
63         tbox->pack_start(*la, false, false, 0);
64 
65         sp_count_v = Gtk::manage(new Gtk::SpinButton());
66         sp_count_v->set_range(4, 512);
67         sp_count_v->set_increments(1, 1);
68         tbox->pack_start(*sp_count_v, false, false, 0);
69 
70         box_top->pack_start(*tbox, false, false, 0);
71     }
72     {
73         cb_xy_lock = Gtk::manage(new Gtk::CheckButton("XY Lock"));
74         cb_xy_lock->signal_toggled().connect(sigc::mem_fun(*this, &FootprintGeneratorGrid::update_xy_lock));
75         cb_xy_lock->set_active(true);
76         box_top->pack_start(*cb_xy_lock, false, false, 0);
77     }
78 
79     sp_count_h->signal_value_changed().connect([this] {
80         pad_count_h = sp_count_h->get_value_as_int();
81         update_preview();
82     });
83     sp_count_v->signal_value_changed().connect([this] {
84         pad_count_v = sp_count_v->get_value_as_int();
85         update_preview();
86     });
87 
88     sp_count_h->set_value(4);
89     sp_count_v->set_value(4);
90 }
91 
update_xy_lock()92 void FootprintGeneratorGrid::update_xy_lock()
93 {
94     auto locked = cb_xy_lock->get_active();
95     sp_pad_width->set_sensitive(!locked);
96     sp_pitch_h->set_sensitive(!locked);
97     if (locked) {
98         sp_pitch_h->set_value(sp_pitch_v->get_value());
99         sp_pad_width->set_value(sp_pad_height->get_value());
100     }
101 }
102 
103 static const std::string bga_letters = "ABCDEFGHJKLMNPRTUVWY";
104 
get_bga_letter(int x)105 static std::string get_bga_letter(int x)
106 {
107     x -= 1;
108     int n_bga_letters = bga_letters.size();
109     if (x < n_bga_letters) {
110         char c[2] = {0};
111         c[0] = bga_letters.at(x);
112         return c;
113     }
114     else {
115         char c[3] = {0};
116         c[0] = bga_letters.at((x / n_bga_letters) - 1);
117         c[1] = bga_letters.at(x % n_bga_letters);
118         return c;
119     }
120 }
121 
generate()122 bool FootprintGeneratorGrid::generate()
123 {
124     if (!property_can_generate())
125         return false;
126     int64_t pitch_h = sp_pitch_h->get_value_as_int();
127     int64_t pitch_v = sp_pitch_v->get_value_as_int();
128     int64_t pad_width = sp_pad_width->get_value_as_int();
129     int64_t pad_height = sp_pad_height->get_value_as_int();
130 
131     auto padstack = core.get_pool().get_padstack(browser_button->property_selected_uuid());
132 
133     for (size_t x = 0; x < pad_count_h; x++) {
134         for (size_t y = 0; y < pad_count_v; y++) {
135             auto uu = UUID::random();
136             auto &pad = package.pads.emplace(uu, Pad(uu, padstack)).first->second;
137             pad.placement.shift.x = pitch_h * x - (pitch_h * (pad_count_h - 1)) / 2;
138             pad.placement.shift.y = -pitch_v * y + (pitch_v * (pad_count_v - 1)) / 2;
139             update_pad_parameters(*padstack, pad, pad_width, pad_height);
140             pad.name = get_bga_letter(x + 1) + std::to_string(y + 1);
141         }
142     }
143     return true;
144 }
145 
update_preview()146 void FootprintGeneratorGrid::update_preview()
147 {
148     overlay->sub_texts["#padx1"] = "A";
149     overlay->sub_texts["#padx2"] = "B";
150     overlay->sub_texts["#padx3"] = get_bga_letter(pad_count_h - 1);
151     overlay->sub_texts["#padx4"] = get_bga_letter(pad_count_h);
152 
153     overlay->sub_texts["#pady1"] = "1";
154     overlay->sub_texts["#pady2"] = "2";
155     overlay->sub_texts["#pady3"] = std::to_string(pad_count_v - 1);
156     overlay->sub_texts["#pady4"] = std::to_string(pad_count_v);
157 
158     overlay->queue_draw();
159 }
160 } // namespace horizon
161