KiCad PCB EDA Suite
Loading...
Searching...
No Matches
transline_dlg_funct.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KICAD, a free EDA CAD application.
3 *
4 * Copyright (C) 2011 jean-pierre.charras
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20#include <cmath>
21
22#include <wx/choicdlg.h>
23#include <wx/filename.h>
24#include <wx/settings.h>
25
26#include <bitmaps.h>
28#include <common_data.h>
32#include <properties/property.h>
33
34
35extern double DoubleFromString( const wxString& TextValue );
36
38{
39 wxArrayString list = StandardRelativeDielectricConstantList();
40 list.Add( "" ); // Add an empty line for no selection
41
42 // Find the previous choice index:
43 wxString prevChoiceStr = m_Value_EpsilonR->GetValue();
44 int prevChoice = 0;
45 findMatch( list, prevChoiceStr, prevChoice );
46
47 int index = wxGetSingleChoiceIndex( wxEmptyString, _( "Relative Dielectric Constants" ),
48 list, prevChoice );
49
50 if( index >= 0 && !list.Item( index ).IsEmpty() ) // i.e. non canceled.
51 m_Value_EpsilonR->SetValue( list.Item( index ).BeforeFirst( ' ' ) );
52}
53
54
55void PANEL_TRANSLINE::OnTranslineTanD_Button( wxCommandEvent& event )
56{
57 wxArrayString list = StandardLossTangentList();
58 list.Add( "" ); // Add an empty line for no selection
59
60 // Find the previous choice index:
61 wxString prevChoiceStr = m_Value_TanD->GetValue();
62 int prevChoice = 0;
63 findMatch( list, prevChoiceStr, prevChoice );
64
65 int index = wxGetSingleChoiceIndex( wxEmptyString, _( "Dielectric Loss Factor" ), list,
66 prevChoice, nullptr );
67
68 if( index >= 0 && !list.Item( index ).IsEmpty() ) // i.e. non canceled.
69 m_Value_TanD->SetValue( list.Item( index ).BeforeFirst( ' ' ) );
70}
71
72
73void PANEL_TRANSLINE::OnTranslineRho_Button( wxCommandEvent& event )
74{
75 wxArrayString list = StandardResistivityList();
76 list.Add( "" ); // Add an empty line for no selection
77
78 // Find the previous choice index:
79 wxString prevChoiceStr = m_Value_Rho->GetValue();
80 int prevChoice = 0;
81 findMatch( list, prevChoiceStr, prevChoice );
82
83 int index = wxGetSingleChoiceIndex( wxEmptyString, _( "Specific Resistance" ), list,
84 prevChoice, nullptr );
85
86 if( index >= 0 && !list.Item( index ).IsEmpty() ) // i.e. non canceled.
87 m_Value_Rho->SetValue( list.Item( index ).BeforeFirst( ' ' ) );
88}
89
90
91// Minor helper struct to handle dialog items for a given parameter
93{
94 wxStaticText* name;
95 wxTextCtrl* value;
97};
98
99
101{
102 m_currTransLineType = aType;
103
106 {
108 }
109
111
112 // This helper bitmap is shown for coupled microstrip only:
113 m_bmCMicrostripZoddZeven->Show( aType == C_MICROSTRIP_TYPE || aType == C_STRIPLINE_TYPE );
115
116 // Soldermask correction applies to microstrip, coupled microstrip, CPW, and CBCPW.
117 // Stripline, coax, waveguide, and twistedpair have no exposed top surface to coat,
118 // so hide the whole group. Fills-gaps is CPW-only.
119 const bool maskEligible = ( aType == MICROSTRIP_TYPE ) || ( aType == C_MICROSTRIP_TYPE )
120 || ( aType == CPW_TYPE ) || ( aType == GROUNDED_CPW_TYPE );
121 const bool cpwFamily = ( aType == CPW_TYPE ) || ( aType == GROUNDED_CPW_TYPE );
122
123 m_soldermaskPresentCheck->Show( maskEligible );
124 m_soldermaskThicknessLabel->Show( maskEligible );
125 m_soldermaskThicknessValue->Show( maskEligible );
126 m_soldermaskThicknessUnit->Show( maskEligible );
127 m_soldermaskEpsilonRLabel->Show( maskEligible );
128 m_soldermaskEpsilonRValue->Show( maskEligible );
129 m_soldermaskTanDLabel->Show( maskEligible );
130 m_soldermaskTanDValue->Show( maskEligible );
131 m_soldermaskFillsGapsCheck->Show( maskEligible && cpwFamily );
132
134
136 m_currTransLine = tr_ident->m_TLine;
137
138 m_radioBtnPrm1->Show( tr_ident->m_HasPrmSelection );
139 m_radioBtnPrm2->Show( tr_ident->m_HasPrmSelection );
140
141 // Setup messages
142 wxStaticText* left_msg_list[] = { m_left_message1, m_left_message2, m_left_message3, m_left_message4,
145
146 wxStaticText* msg_list[] = { m_Message1, m_Message2, m_Message3, m_Message4, m_Message5, m_Message6,
148
149 unsigned jj = 0;
150
151 for( ; jj < tr_ident->m_Messages.GetCount(); jj++ )
152 {
153 if( left_msg_list[jj] == nullptr )
154 break;
155
156 left_msg_list[jj]->SetLabel( tr_ident->m_Messages[jj] );
157 msg_list[jj]->SetLabel( wxEmptyString );
158 }
159
160 while( left_msg_list[jj] )
161 {
162 left_msg_list[jj]->SetLabel( wxEmptyString );
163 msg_list[jj]->SetLabel( wxEmptyString );
164 jj++;
165 }
166
167
168 // Init parameters dialog items
169 struct DLG_PRM_DATA substrateprms[] =
170 {
172 { m_TanD_label, m_Value_TanD, nullptr },
173 { m_Rho_label, m_Value_Rho, nullptr },
180 };
181
182#define substrateprms_cnt (sizeof(substrateprms)/sizeof(substrateprms[0]))
183
184 struct DLG_PRM_DATA physprms[] =
185 {
189 };
190
191#define physprms_cnt (sizeof(physprms)/sizeof(physprms[0]))
192
193 struct DLG_PRM_DATA elecprms[] =
194 {
198 };
199
200#define elecprms_cnt (sizeof(elecprms)/sizeof(elecprms[0]))
201
202 struct DLG_PRM_DATA frequencyprms[] =
203 {
205 };
206
207#define frequencyprms_cnt (sizeof(frequencyprms)/sizeof(frequencyprms[0]))
208
209 unsigned idxsubs = 0;
210 unsigned idxphys = 0;
211 unsigned idxelec = 0;
212 unsigned idxfreq = 0;
213
214 for( unsigned ii = 0; ii < tr_ident->GetPrmsCount(); ii++ )
215 {
216 TRANSLINE_PRM* prm = tr_ident->GetPrm( ii );
217 struct DLG_PRM_DATA * data = nullptr;
218
219 switch( prm->m_Type )
220 {
221 case PRM_TYPE_SUBS:
222 wxASSERT( idxsubs < substrateprms_cnt );
223 data = &substrateprms[idxsubs];
224 idxsubs++;
225 break;
226
227 case PRM_TYPE_PHYS:
228 wxASSERT( idxphys < physprms_cnt );
229 data = &physprms[idxphys];
230 idxphys++;
231 break;
232
233 case PRM_TYPE_ELEC:
234 wxASSERT( idxelec < elecprms_cnt );
235 data = &elecprms[idxelec];
236 idxelec++;
237 break;
238
240 wxASSERT( idxfreq < frequencyprms_cnt );
241 data = &frequencyprms[idxfreq];
242 idxfreq++;
243 break;
244 }
245
246 wxASSERT ( data );
247 data->name->SetToolTip( prm->m_ToolTip );
248 data->name->SetLabel( prm->m_DlgLabel != wxS( "" ) ? prm->m_DlgLabel + wxS( ':' ) : wxString( wxS( "" ) ) );
249 prm->m_ValueCtrl = data->value;
250
251 if( prm->m_Id != DUMMY_PRM )
252 {
253 data->value->SetValue( wxString::Format( wxS( "%g" ), prm->m_Value ) );
254 data->value->Enable( true );
255 }
256 else
257 {
258 data->value->SetValue( wxEmptyString );
259 data->value->Enable( false );
260 }
261
262 if( prm->m_ConvUnit )
263 prm->m_UnitCtrl = data->unit;
264
265 if( data->unit )
266 {
267 data->unit->Show( prm->m_ConvUnit );
268 data->unit->Enable( prm->m_ConvUnit );
269 data->unit->SetSelection( prm->m_UnitSelection );
270 }
271 }
272
273 // Clear all unused params
274 for( ; idxsubs < substrateprms_cnt; idxsubs++ )
275 {
276 substrateprms[idxsubs].name->SetLabel(wxEmptyString);
277 substrateprms[idxsubs].name->SetToolTip(wxEmptyString);
278 substrateprms[idxsubs].value->SetValue(wxEmptyString);
279 substrateprms[idxsubs].value->Enable( false );
280
281 if( substrateprms[idxsubs].unit)
282 {
283 substrateprms[idxsubs].unit->Show( false );
284 substrateprms[idxsubs].unit->Enable( false );
285 substrateprms[idxsubs].unit->SetSelection( 0 );
286 }
287 }
288
289 for( ; idxphys < physprms_cnt; idxphys++ )
290 {
291 physprms[idxphys].name->SetLabel(wxEmptyString);
292 physprms[idxphys].name->SetToolTip(wxEmptyString);
293 physprms[idxphys].value->SetValue(wxEmptyString);
294 physprms[idxphys].value->Enable( false );
295
296 if( physprms[idxphys].unit)
297 {
298 physprms[idxphys].unit->Show( false );
299 physprms[idxphys].unit->Enable( false );
300 physprms[idxphys].unit->SetSelection( 0 );
301 }
302 }
303
304 for( ; idxelec < elecprms_cnt; idxelec++)
305 {
306 elecprms[idxelec].name->SetLabel(wxEmptyString);
307 elecprms[idxelec].name->SetToolTip(wxEmptyString);
308 elecprms[idxelec].value->SetValue(wxEmptyString);
309 elecprms[idxelec].value->Enable( false );
310
311 if( elecprms[idxelec].unit)
312 {
313 elecprms[idxelec].unit->Show( false );
314 elecprms[idxelec].unit->Enable( false );
315 elecprms[idxelec].unit->SetSelection( 0 );
316 }
317 }
318
319 for( ; idxfreq < frequencyprms_cnt; idxfreq++ )
320 {
321 frequencyprms[idxfreq].name->SetLabel(wxEmptyString);
322 frequencyprms[idxfreq].name->SetToolTip(wxEmptyString);
323 frequencyprms[idxfreq].value->SetValue(wxEmptyString);
324 frequencyprms[idxfreq].value->Enable( false );
325
326 if( frequencyprms[idxfreq].unit )
327 {
328 frequencyprms[idxfreq].unit->Show( false );
329 frequencyprms[idxfreq].unit->Enable( false );
330 frequencyprms[idxfreq].unit->SetSelection( 0 );
331 }
332 }
333}
334
335
337{
339
340 for( unsigned ii = 0; ii < tr_ident->GetPrmsCount(); ii++ )
341 {
342 TRANSLINE_PRM* prm = tr_ident->GetPrm( ii );
343 wxTextCtrl * value_ctrl = (wxTextCtrl * ) prm->m_ValueCtrl;
344 wxString value_txt = value_ctrl->GetValue();
345 double value = DoubleFromString(value_txt);
346 prm->m_Value = value;
347 UNIT_SELECTOR * unit_ctrl = (UNIT_SELECTOR * ) prm->m_UnitCtrl;
348
349 if( unit_ctrl )
350 {
351 prm->m_UnitSelection = unit_ctrl->GetSelection();
352 value *= unit_ctrl->GetUnitScale();
353 }
354
355 prm->m_NormalizedValue = value;
356 }
357
358 // Panel-level selections are not part of the per-calculator param list and must be
359 // pushed explicitly.
360 if( m_currTransLine )
361 {
362 const int modelSel = m_dielectricModelChoice ? m_dielectricModelChoice->GetSelection() : 0;
363 m_currTransLine->SetExtraParameter( DIELECTRIC_MODEL_PRM, static_cast<double>( modelSel ) );
364
366 {
367 const double fSpec = DoubleFromString( m_Value_SpecFrequency_Ctrl->GetValue() )
368 * m_choiceUnit_SpecFrequency->GetUnitScale();
369
370 if( std::isfinite( fSpec ) && fSpec > 0.0 )
371 m_currTransLine->SetExtraParameter( EPSILONR_SPEC_FREQ_PRM, fSpec );
372 }
373
374 // Soldermask panel values. Thickness is entered in micrometres; convert to metres to
375 // match the math backend. If the checkbox is off, SOLDERMASK_PRESENT = 0 forces a
376 // bit-identical result regardless of the other mask fields.
377 const double present = m_soldermaskPresentCheck->GetValue() ? 1.0 : 0.0;
378 m_currTransLine->SetExtraParameter( SOLDERMASK_PRESENT_PRM, present );
379
380 // DoubleFromString handles "20 um" suffixes, comma decimal separators, and 1e3
381 // notation; on parse failure it returns NaN. Push the NaN through so the
382 // backend / checkProperties surfaces the bad input instead of silently retaining
383 // the previously-valid value (which would let the UI text and analysis state
384 // diverge).
385 const double thicknessUm = DoubleFromString( m_soldermaskThicknessValue->GetValue() );
386 m_currTransLine->SetExtraParameter( SOLDERMASK_THICKNESS_PRM, thicknessUm * 1.0e-6 );
387
388 const double epsR = DoubleFromString( m_soldermaskEpsilonRValue->GetValue() );
389 m_currTransLine->SetExtraParameter( SOLDERMASK_EPSILONR_PRM, epsR );
390
391 const double tand = DoubleFromString( m_soldermaskTanDValue->GetValue() );
392 m_currTransLine->SetExtraParameter( SOLDERMASK_TAND_PRM, tand );
393
394 const double fillsGaps = m_soldermaskFillsGapsCheck->GetValue() ? 1.0 : 0.0;
395 m_currTransLine->SetExtraParameter( SOLDERMASK_FILLS_GAPS_PRM, fillsGaps );
396 }
397}
398
399
400void PANEL_TRANSLINE::OnTranslineSelection( wxCommandEvent& event )
401{
402 // Ensure parameters from current selection are taken in account before switching to a new selection
403 if( m_currTransLine )
405
406 enum TRANSLINE_TYPE_ID id = (enum TRANSLINE_TYPE_ID) event.GetSelection();
407
409
410 // Texts and units choice widgets can have their size modified:
411 // The new size must be taken in account
412 GetSizer()->Layout();
413 Refresh();
414}
415
416
418{
419 // Initialize param values to default value
421
422 for( unsigned ii = 0; ii < tr_ident->GetPrmsCount(); ii++ )
423 {
424 TRANSLINE_PRM* prm = tr_ident->GetPrm( ii );
425 prm->m_Value = prm->m_DefaultValue;
426 UNIT_SELECTOR* unit_ctrl = (UNIT_SELECTOR*) prm->m_UnitCtrl;
427
428 if( unit_ctrl )
429 prm->m_UnitSelection = prm->m_DefaultUnit;
430 }
431
432 // Reinit displayed values
434
435 Refresh();
436}
int index
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
@ microstrip_zodd_zeven
wxTextCtrl * m_Substrate_prm5_Value
UNIT_SELECTOR_RESISTOR * m_choiceUnit_ElecPrm2
UNIT_SELECTOR_LEN * m_SubsPrm9_choiceUnit
wxStaticText * m_soldermaskTanDLabel
wxStaticText * m_substrate_prm9_label
wxTextCtrl * m_Substrate_prm9_Value
UNIT_SELECTOR_FREQUENCY * m_choiceUnit_SpecFrequency
wxStaticText * m_soldermaskEpsilonRLabel
UNIT_SELECTOR_LEN * m_SubsPrm4_choiceUnit
wxStaticText * m_EpsilonR_label
wxStaticText * m_substrate_prm7_label
wxStaticText * m_Frequency_label
wxTextCtrl * m_Substrate_prm7_Value
wxStaticBitmap * m_bmCMicrostripZoddZeven
wxStaticText * m_substrate_prm6_label
UNIT_SELECTOR_LEN * m_SubsPrm7_choiceUnit
UNIT_SELECTOR_LEN * m_choiceUnit_Param3
wxTextCtrl * m_soldermaskThicknessValue
wxTextCtrl * m_Substrate_prm4_Value
wxCheckBox * m_soldermaskPresentCheck
UNIT_SELECTOR_LEN * m_SubsPrm5_choiceUnit
wxTextCtrl * m_Substrate_prm6_Value
wxStaticText * m_substrate_prm8_label
wxStaticText * m_soldermaskThicknessUnit
wxCheckBox * m_soldermaskFillsGapsCheck
UNIT_SELECTOR_ANGLE * m_choiceUnit_ElecPrm3
UNIT_SELECTOR_LEN * m_SubsPrm6_choiceUnit
wxStaticBitmap * m_translineBitmap
UNIT_SELECTOR_LEN * m_choiceUnit_Param2
UNIT_SELECTOR_FREQUENCY * m_choiceUnit_Frequency
UNIT_SELECTOR_LEN * m_SubsPrm8_choiceUnit
wxTextCtrl * m_soldermaskEpsilonRValue
wxTextCtrl * m_Substrate_prm8_Value
UNIT_SELECTOR_RESISTOR * m_choiceUnit_ElecPrm1
wxStaticText * m_substrate_prm4_label
UNIT_SELECTOR_LEN * m_choiceUnit_Param1
wxStaticText * m_soldermaskThicknessLabel
wxStaticText * m_substrate_prm5_label
wxTextCtrl * m_Value_Frequency_Ctrl
wxTextCtrl * m_Value_SpecFrequency_Ctrl
TRANSLINE * m_currTransLine
void OnTranslineTanD_Button(wxCommandEvent &event) override
Show a list of current dielectric loss factor (tangent delta) and set the selected value in main dial...
void TranslineTypeSelection(enum TRANSLINE_TYPE_ID aType)
Must be called after selection of a new transline.
void OnTranslineEpsilonR_Button(wxCommandEvent &event) override
Shows a list of current relative dielectric constant(Er) and set the selected value in main dialog fr...
void updateSoldermaskEnables()
Apply the enabled state for the soldermask row based on the present checkbox and the current calculat...
void TransfDlgDataToTranslineParams()
Read values entered in dialog frame, and transfer these values in current transline parameters,...
void OnTranslineSelection(wxCommandEvent &event) override
Called on new transmission line selection.
std::vector< TRANSLINE_IDENT * > m_transline_list
void OnTransLineResetButtonClick(wxCommandEvent &event) override
Called when the user clicks the reset button; sets the parameters to their default values.
void OnTranslineRho_Button(wxCommandEvent &event) override
Show a list of current Specific resistance list (rho) and set the selected value in main dialog frame...
enum TRANSLINE_TYPE_ID m_currTransLineType
A class to handle a list of parameters of a given transline.
TRANSLINE * m_TLine
unsigned GetPrmsCount() const
TRANSLINE_PRM * GetPrm(unsigned aIdx) const
wxArrayString m_Messages
A class to handle one parameter of transline.
double m_NormalizedValue
wxString m_DlgLabel
virtual double GetUnitScale()=0
Function GetUnitScale.
wxArrayString StandardResistivityList()
wxArrayString StandardRelativeDielectricConstantList()
wxArrayString StandardLossTangentList()
#define _(s)
double DoubleFromString(const wxString &TextValue)
bool findMatch(wxArrayString &aList, const wxString &aValue, int &aIdx)
wxStaticText * name
UNIT_SELECTOR * unit
@ SOLDERMASK_FILLS_GAPS_PRM
Definition transline.h:83
@ SOLDERMASK_PRESENT_PRM
Definition transline.h:79
@ DIELECTRIC_MODEL_PRM
Definition transline.h:77
@ EPSILONR_SPEC_FREQ_PRM
Definition transline.h:78
@ SOLDERMASK_TAND_PRM
Definition transline.h:82
@ SOLDERMASK_EPSILONR_PRM
Definition transline.h:81
@ SOLDERMASK_THICKNESS_PRM
Definition transline.h:80
@ DUMMY_PRM
Definition transline.h:63
#define elecprms_cnt
#define substrateprms_cnt
double DoubleFromString(const wxString &TextValue)
#define frequencyprms_cnt
#define physprms_cnt
@ PRM_TYPE_FREQUENCY
@ PRM_TYPE_SUBS
@ PRM_TYPE_ELEC
@ PRM_TYPE_PHYS
TRANSLINE_TYPE_ID
@ MICROSTRIP_TYPE
@ CPW_TYPE
@ GROUNDED_CPW_TYPE
@ C_MICROSTRIP_TYPE
@ END_OF_LIST_TYPE
@ DEFAULT_TYPE
@ START_OF_LIST_TYPE
@ C_STRIPLINE_TYPE