KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_io_ltspice_parser.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) 2022 Chetan Subhash Shinde<[email protected]>
5 * Copyright (C) 2023 CERN
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
26
29#include <schematic.h>
30#include <sch_line.h>
31#include <sch_label.h>
32#include <sch_text.h>
33#include <sch_edit_frame.h>
34#include <sch_shape.h>
35#include <sch_bus_entry.h>
36#include <wx/buffer.h>
37#include <wx/ffile.h>
38#include <wx/filename.h>
39#include <wx/strconv.h>
40#include <wx/tokenzr.h>
41#include <wx/txtstrm.h>
42#include <wx/wfstream.h>
43#include <sim/spice_value.h>
44#include <fmt/format.h>
45#include <cmath>
46#include <set>
47
48
49// Split PWL argument strings on whitespace while keeping quoted spans intact.
50// Example input: REPEAT FOREVER FILE="data 3.txt" ENDREPEAT
51// Example tokens: [REPEAT] [FOREVER] [FILE="data 3.txt"] [ENDREPEAT]
52static std::vector<wxString> tokenizeQuoted( const wxString& aText )
53{
54 std::vector<wxString> tokens;
55 wxString token;
56 bool inQuotes = false;
57
58 for( wxUniChar ch : aText )
59 {
60 if( ch == '"' )
61 inQuotes = !inQuotes;
62
63 if( !inQuotes && wxIsspace( ch ) )
64 {
65 if( !token.IsEmpty() )
66 {
67 tokens.push_back( token );
68 token.clear();
69 }
70 }
71 else
72 {
73 token += ch;
74 }
75 }
76
77 if( !token.IsEmpty() )
78 tokens.push_back( token );
79
80 return tokens;
81}
82
83
84// LTspice .tran -> ngspice .tran. Tstep 0 or omitted -> (Tstop-Tstart)/10000.
85// Time values are rewritten; trailing modifiers (uic, steady, ...) are kept as-is.
86static wxString convertLtSpiceTextToNgspice( const wxString& aText )
87{
88 wxArrayString outLines;
89
90 for( wxString line : wxSplit( aText, '\n', '\0' ) )
91 {
92 wxArrayString tok = wxSplit( line, ' ', '\0' );
93
94 if( !tok.IsEmpty() && tok[0].IsSameAs( wxS( ".tran" ), false ) )
95 {
96 wxArrayString args; // <Tstep> <Tstop> [Tstart [dTmax]] [modifiers]
97 wxArrayString modifiers; // uic / LTspice-only flags, preserved
98
99 const std::set<wxString> c_modifiers = { "UIC", "STEADY", "NODISCARD", "STARTUP", "STEP" };
100
101 for( size_t i = 1; i < tok.size(); ++i )
102 {
103 if( tok[i].IsEmpty() )
104 continue;
105
106 wxString u = tok[i].Upper();
107
108 if( modifiers.IsEmpty() && !c_modifiers.contains( u ) )
109 args.Add( tok[i] );
110 else
111 modifiers.Add( tok[i] );
112 }
113
114 if( !args.IsEmpty() )
115 {
116 // LTspice syntax:
117 // .TRAN <Tstep> <Tstop> [Tstart [dTmax]] [modifiers]
118 // .TRAN <Tstop> [modifiers]
119
120 // ngspice syntax:
121 // .tran tstep tstop <tstart <tmax>> <uic>
122 const bool hasTstep = args.size() >= 2;
123
124 wxString tstepStr = hasTstep ? args[0] : wxString();
125 wxString tstopStr = hasTstep ? args[1] : args[0];
126 wxString tstartStr = ( args.size() > 2 ) ? args[2] : wxString();
127 wxString dtmaxStr = ( args.size() > 3 ) ? args[3] : wxString();
128
129 double tstep = SPICE_VALUE( tstepStr ).ToDouble();
130 double tstop = SPICE_VALUE( tstopStr ).ToDouble();
131 double tstart = SPICE_VALUE( tstartStr ).ToDouble();
132
133 if( tstep == 0.0 )
134 tstepStr = SPICE_VALUE( ( tstop - tstart ) / 10000.0 ).ToSpiceString();
135
136 line = wxS( ".tran " ) + tstepStr + wxS( " " ) + tstopStr;
137
138 if( !tstartStr.IsEmpty() )
139 line << wxS( " " ) << tstartStr;
140
141 if( !dtmaxStr.IsEmpty() )
142 line << wxS( " " ) << dtmaxStr;
143
144 for( const wxString& mod : modifiers )
145 line << wxS( " " ) << mod;
146 }
147 }
148
149 outLines.Add( line );
150 }
151
152 return wxJoin( outLines, '\n', '\0' );
153}
154
155
156// Convert an LTspice PWL data file to an ngspice-friendly version.
157// Input semantics: "+t" is relative and plain "t" is absolute time.
158// Output semantics: emit relative step durations on every line.
159static bool convertPwlFileToNgspice( const wxFileName& aSourceFile, const wxFileName& aDestFile )
160{
161 wxFFileInputStream inputStream( aSourceFile.GetFullPath() );
162
163 if( !inputStream.IsOk() )
164 return false;
165
166 wxFFileOutputStream outputStream( aDestFile.GetFullPath() );
167
168 if( !outputStream.IsOk() )
169 return false;
170
171 wxTextInputStream textIn( inputStream, wxS( " \t" ), wxConvUTF8 );
172 wxTextOutputStream textOut( outputStream, wxEOL_UNIX, wxConvUTF8 );
173 double prevAbsoluteTime = 0.0;
174
175 while( inputStream.CanRead() )
176 {
177 wxString line = textIn.ReadLine();
178 line.Trim( true ).Trim( false );
179
180 // Convert comments to # format known by ngspice
181 wxString commentRest;
182 if( line.StartsWith( wxS( "*" ), &commentRest ) || line.StartsWith( wxS( ";" ), &commentRest ) )
183 {
184 textOut << wxS( "#" ) << commentRest << '\n';
185 continue;
186 }
187
188 wxStringTokenizer pointTokenizer( line, wxS( " \t" ), wxTOKEN_STRTOK );
189
190 if( pointTokenizer.CountTokens() < 2 )
191 {
192 textOut << line << '\n';
193 continue;
194 }
195
196 wxString timeToken = pointTokenizer.GetNextToken();
197 wxString valueToken = pointTokenizer.GetNextToken();
198
199 // LTspice semantics: "+t" means offset from previous point, plain "t"
200 // means absolute time from 0.
201 // Example: 0 0, +100n 0, 300n 1 => absolute times 0, 100n, 300n.
202 wxString timeRest = timeToken;
203 bool isRelative = timeToken.StartsWith( wxS( "+" ), &timeRest );
204
205 if( timeRest.IsEmpty() )
206 {
207 textOut << line << '\n';
208 continue;
209 }
210
211 // Parse LTspice time token to seconds
212 SPICE_VALUE spiceValue( timeRest );
213 double timeValueSeconds = spiceValue.ToDouble();
214
215 // Convert to relative time
216 double absoluteTime = isRelative ? prevAbsoluteTime + timeValueSeconds : timeValueSeconds;
217 double relativeTime = absoluteTime - prevAbsoluteTime;
218 prevAbsoluteTime = absoluteTime;
219
220 // Format seconds using explicit engineering notation (e.g. 1e-7 -> 100e-9).
221 wxString relativeTimeStr = wxS( "0" );
222
223 if( relativeTime != 0.0 )
224 {
225 double absSeconds = std::fabs( relativeTime );
226 int exp10 = static_cast<int>( std::floor( std::log10( absSeconds ) ) );
227 int engExp = exp10 - ( ( exp10 % 3 + 3 ) % 3 );
228 double mantissa = relativeTime / std::pow( 10.0, engExp );
229
230 relativeTimeStr = wxString::FromUTF8( fmt::format( "{:.9g}e{}", mantissa, engExp ) );
231 }
232
233 textOut << relativeTimeStr << '\t' << valueToken << '\n';
234 }
235
236 return outputStream.IsOk();
237}
238
239
241 std::vector<LTSPICE_SCHEMATIC::LT_ASC>& outLT_ASCs,
242 const std::vector<wxString>& aAsyFileNames )
243{
244 // Center created objects in Kicad page
245 BOX2I bbox;
246
247 for( const LTSPICE_SCHEMATIC::LT_ASC& asc : outLT_ASCs )
248 bbox.Merge( asc.BoundingBox );
249
250 m_originOffset = { 0, 0 };
251 bbox.SetOrigin( ToKicadCoords( bbox.GetOrigin() ) );
252 bbox.SetSize( ToKicadCoords( bbox.GetSize() ) );
253
254 VECTOR2I pageSize = aSheet->LastScreen()->GetPageSettings().GetSizeIU( schIUScale.IU_PER_MILS );
255 int grid = schIUScale.MilsToIU( 50 );
256 int margin = grid * 10;
257
258 m_originOffset = ( pageSize / 2 ) - bbox.GetCenter();
259
260 if( bbox.GetWidth() > pageSize.x - margin )
261 m_originOffset.x = margin - bbox.GetLeft();
262
263 if( bbox.GetHeight() > pageSize.y - margin )
264 m_originOffset.y = margin - bbox.GetTop();
265
267
268 CreateKicadSYMBOLs( aSheet, outLT_ASCs, aAsyFileNames );
269 CreateKicadSCH_ITEMs( aSheet, outLT_ASCs );
270
271 // Convert LTspice standard device libs to UTF-8 into ltspice_cmp/ and .include them.
272 wxString projectPath;
273 wxString includeText;
274
275 if( SCHEMATIC* schematic = aSheet->LastScreen()->Schematic() )
276 projectPath = schematic->Project().GetProjectPath();
277
278 if( !projectPath.IsEmpty() )
279 {
280 wxFileName cmpDir( m_lt_schematic->GetLTspiceDataDir().GetFullPath(), wxEmptyString );
281 cmpDir.AppendDir( wxS( "cmp" ) );
282
283 wxFileName outDir( projectPath, wxEmptyString );
284 outDir.AppendDir( wxS( "ltspice_cmp" ) );
285 outDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
286
287 for( const wxString name :
288 { wxS( "standard.dio" ), wxS( "standard.bjt" ), wxS( "standard.jft" ), wxS( "standard.mos" ) } )
289 {
290 includeText << wxS( ".include ltspice_cmp/" ) << name << wxS( "\n" );
291
292 wxFileName src = cmpDir;
293 src.SetFullName( name );
294
295 if( !src.FileExists() )
296 continue;
297
298 wxFileName dst = outDir;
299 dst.SetFullName( name );
300
301 if( dst.FileExists() )
302 continue;
303
304 wxFFile in( src.GetFullPath(), wxS( "rb" ) );
305
306 if( !in.IsOpened() )
307 continue;
308
309 wxFileOffset len = in.Length();
310
311 if( len <= 0 )
312 continue;
313
314 wxMemoryBuffer buffer( static_cast<size_t>( len ) );
315 void* writePtr = buffer.GetWriteBuf( static_cast<size_t>( len ) );
316
317 if( !writePtr || in.Read( writePtr, len ) != static_cast<size_t>( len ) )
318 continue;
319
320 buffer.UngetWriteBuf( static_cast<size_t>( len ) );
321
322 const char* data = static_cast<const char*>( buffer.GetData() );
323 wxString text;
324
325 // UTF-16 LE looks like c \0 c \0 ...; else try UTF-8, then CP1252.
326 if( len >= 4 && ( len % 2 ) == 0 && data[1] == 0 && data[3] == 0 )
327 text = wxString( data, wxMBConvUTF16LE(), len );
328 else
329 text = wxString::FromUTF8( data, len );
330
331 if( text.empty() )
332 text = wxString( data, wxCSConv( wxFONTENCODING_CP1252 ), len );
333
334 wxFFile out( dst.GetFullPath(), wxS( "wb" ) );
335
336 if( !out.IsOpened() )
337 continue;
338
339 out.Write( text, wxConvUTF8 );
340 }
341 }
342
343 // Add filesource subcircuit template for PWL file sources
344 includeText << wxS( "\n" );
345 includeText << wxS( ".subckt pwl_file outp outn file=\"\" timerelative=1\n" );
346 includeText << wxS( "Afs %vd([outp outn]) filesrc\n" );
347 includeText << wxS( ".model filesrc filesource (file={file} amploffset=[0] amplscale=[1] timeoffset=0 "
348 "timescale=1 timerelative={timerelative})\n" );
349 includeText << wxS( ".ends\n" );
350
351 if( !includeText.IsEmpty() )
352 {
353 SCH_TEXT* textItem = new SCH_TEXT( VECTOR2I( 0, 0 ), includeText );
354
355 textItem->SetVisible( true );
356 textItem->SetMultilineAllowed( true );
359
360 aSheet->LastScreen()->Append( textItem );
361 }
362}
363
364
367 int aIndex, SCH_SHAPE* shape )
368{
369 LTSPICE_SCHEMATIC::LINE& lt_line = aLTSymbol.Lines[aIndex];
370
371 shape->AddPoint( ToKicadCoords( lt_line.End ) );
372 shape->AddPoint( ToKicadCoords( lt_line.Start ) );
373 shape->SetStroke( getStroke( lt_line.LineWidth, lt_line.LineStyle ) );
374}
375
376
378 SCH_SHEET_PATH* aSheet )
379{
380 LTSPICE_SCHEMATIC::LINE& lt_line = aLTSymbol.Lines[aIndex];
381 SCH_SHAPE* shape = new SCH_SHAPE( SHAPE_T::POLY );
382
383 shape->AddPoint( ToKicadCoords( lt_line.End ) );
384 shape->AddPoint( ToKicadCoords( lt_line.Start ) );
385 shape->SetStroke( getStroke( lt_line.LineWidth, lt_line.LineStyle ) );
386
387 shape->Move( ToKicadCoords( aLTSymbol.Offset ) + m_originOffset );
388 RotateMirrorShape( aLTSymbol, shape );
389
390 aSheet->LastScreen()->Append( shape );
391}
392
393
395 std::vector<LTSPICE_SCHEMATIC::LT_ASC>& outLT_ASCs,
396 const std::vector<wxString>& aAsyFiles )
397{
398 for( LTSPICE_SCHEMATIC::LT_ASC& lt_asc : outLT_ASCs )
399 {
400 std::vector<LTSPICE_SCHEMATIC::LT_SYMBOL> symbols = lt_asc.Symbols;
401 std::map<wxString, LIB_SYMBOL*> existingSymbol;
402 std::map<wxString, SCH_SYMBOL*> existingSchematicSymbol;
403
404 for( LTSPICE_SCHEMATIC::LT_SYMBOL& lt_symbol : symbols )
405 {
406 if( !alg::contains( aAsyFiles, lt_symbol.Name ) )
407 {
408 LIB_SYMBOL* lib_symbol;
409
410 if( existingSymbol.count( lt_symbol.Name ) == 0 )
411 {
412 lib_symbol = new LIB_SYMBOL( lt_symbol.Name );
413
414 CreateSymbol( lt_symbol, lib_symbol );
415
416 existingSymbol.emplace( lt_symbol.Name, lib_symbol );
417 }
418 else
419 {
420 lib_symbol = existingSymbol[lt_symbol.Name];
421 }
422
423 LIB_ID libId( wxS( "ltspice" ), lt_symbol.Name );
424 SCH_SYMBOL* sch_symbol = new SCH_SYMBOL( *lib_symbol, libId, aSheet, 1 );
425
426 CreateFields( lt_symbol, sch_symbol, aSheet );
427
428 for( int j = 0; j < (int) lt_symbol.Wires.size(); j++ )
429 CreateWires( lt_symbol, j, aSheet );
430
431 sch_symbol->Move( ToKicadCoords( lt_symbol.Offset ) + m_originOffset );
432 RotateMirror( lt_symbol, sch_symbol );
433
434 aSheet->LastScreen()->Append( sch_symbol );
435 }
436 else
437 {
438 for( int j = 0; j < (int) lt_symbol.Lines.size(); j++ )
439 CreateLines( lt_symbol, j, aSheet );
440
441 for( int j = 0; j < (int) lt_symbol.Circles.size(); j++ )
442 CreateCircle( lt_symbol, j, aSheet );
443
444 for( int j = 0; j < (int) lt_symbol.Arcs.size(); j++ )
445 CreateArc( lt_symbol, j, aSheet );
446
447 for( int j = 0; j < (int) lt_symbol.Rectangles.size(); j++ )
448 CreateRect( lt_symbol, j, aSheet );
449
450 // Calculating bounding box
451 BOX2I bbox;
452
454 LTSPICE_FILE tempAsyFile( lt_symbol.Name + ".asy", { 0, 0 } );
456
457 tempSymbol = m_lt_schematic->SymbolBuilder( lt_symbol.Name, dummyAsc );
458
459 LIB_SYMBOL* tempLibSymbol = new LIB_SYMBOL( lt_symbol.Name );
460 CreateSymbol( tempSymbol, tempLibSymbol );
461
462 bbox = tempLibSymbol->GetBoundingBox();
463
464 int topLeftX = lt_symbol.Offset.x + ToLtSpiceCoords( bbox.GetOrigin().x );
465 int topLeftY = lt_symbol.Offset.y + ToLtSpiceCoords( bbox.GetOrigin().y );
466 int botRightX = lt_symbol.Offset.x
467 + ToLtSpiceCoords( bbox.GetOrigin().x )
468 + ToLtSpiceCoords( bbox.GetSize().x );
469 int botRightY = lt_symbol.Offset.y
470 + ToLtSpiceCoords( bbox.GetOrigin().y )
471 + ToLtSpiceCoords( bbox.GetSize().y );
472
473 for( LTSPICE_SCHEMATIC::LT_PIN& pin : lt_symbol.Pins )
474 {
475 VECTOR2I pinPos = pin.PinLocation;
476
477 for( LTSPICE_SCHEMATIC::WIRE& wire : lt_asc.Wires )
478 {
479 if( wire.Start == ( pinPos + lt_symbol.Offset ) )
480 {
481 //wire is vertical
482 if( wire.End.x == ( pinPos + lt_symbol.Offset ).x )
483 {
484 if( wire.End.y <= topLeftY )
485 wire.Start = VECTOR2I( wire.Start.x, topLeftY + 3 );
486 else if( wire.End.y >= botRightY )
487 wire.Start = VECTOR2I( wire.Start.x, botRightY );
488 else if( wire.End.y < botRightY && wire.End.y > topLeftY )
489 wire.Start = VECTOR2I( topLeftX, wire.Start.y );
490 }
491 //wire is horizontal
492 else if( wire.End.y == ( pinPos + lt_symbol.Offset ).y )
493 {
494 if( wire.End.x <= topLeftX )
495 wire.Start = VECTOR2I( topLeftX, wire.Start.y );
496 else if( wire.End.x >= botRightX )
497 wire.Start = VECTOR2I( botRightX, wire.Start.y );
498 else if( wire.End.x < botRightX && wire.End.x > topLeftX )
499 wire.Start = VECTOR2I( botRightX, wire.Start.y );
500 }
501 }
502 else if( wire.End == ( pinPos + lt_symbol.Offset ) )
503 {
504 //wire is Vertical
505 if( wire.Start.x == ( pinPos + lt_symbol.Offset ).x )
506 {
507 if( wire.Start.y <= topLeftY )
508 wire.End = VECTOR2I( wire.End.x, topLeftY );
509 else if( wire.Start.y > botRightY )
510 wire.End = VECTOR2I( wire.End.x, botRightY );
511 else if( wire.Start.y < botRightY && wire.End.y > topLeftY )
512 wire.End = VECTOR2I( wire.End.x, botRightY );
513 }
514 //wire is Horizontal
515 else if( wire.Start.y == ( pinPos + lt_symbol.Offset ).y )
516 {
517 if( wire.Start.x <= topLeftX )
518 wire.End = VECTOR2I( topLeftX, wire.End.y );
519 else if( wire.Start.x >= botRightX )
520 wire.End = VECTOR2I( botRightX, wire.End.y );
521 else if( wire.Start.x < botRightX && wire.Start.x > topLeftX )
522 wire.End = VECTOR2I( botRightX, wire.End.y );
523 }
524 }
525 }
526 }
527 }
528 }
529 }
530}
531
532
534 LIB_SYMBOL* aLibSymbol )
535{
536 for( int j = 0; j < (int) aLtSymbol.Lines.size(); j++ )
537 {
539
540 CreateLines( aLibSymbol, aLtSymbol, j, line );
541 aLibSymbol->AddDrawItem( line );
542 }
543
544 for( int j = 0; j < (int) aLtSymbol.Circles.size(); j++ )
545 {
547
548 CreateCircle( aLtSymbol, j, circle );
549 aLibSymbol->AddDrawItem( circle );
550 }
551
552 for( int j = 0; j < (int) aLtSymbol.Arcs.size(); j++ )
553 {
555
556 CreateArc( aLtSymbol, j, arc );
557 aLibSymbol->AddDrawItem( arc );
558 }
559
560 for( int j = 0; j < (int) aLtSymbol.Rectangles.size(); j++ )
561 {
563
564 CreateRect( aLtSymbol, j, rectangle );
565 aLibSymbol->AddDrawItem( rectangle );
566 }
567
568 for( int j = 0; j < (int) aLtSymbol.Pins.size(); j++ )
569 {
570 SCH_PIN* pin = new SCH_PIN( aLibSymbol );
571
572 CreatePin( aLtSymbol, j, pin );
573 aLibSymbol->AddDrawItem( pin );
574 }
575
576 aLibSymbol->SetShowPinNumbers( false );
577}
578
579
581{
582 return schIUScale.MilsToIU( rescale( 50, aCoordinate, 16 ) );
583}
584
585
587{
588 return VECTOR2I( ToKicadCoords( aPos.x ), ToKicadCoords( aPos.y ) );
589}
590
591
593{
594 auto MILS_SIZE =
595 []( int mils )
596 {
597 return VECTOR2I( schIUScale.MilsToIU( mils ), schIUScale.MilsToIU( mils ) );
598 };
599
600 if( aLTFontSize == 1 ) return MILS_SIZE( 36 );
601 else if( aLTFontSize == 2 ) return MILS_SIZE( 42 );
602 else if( aLTFontSize == 3 ) return MILS_SIZE( 50 );
603 else if( aLTFontSize == 4 ) return MILS_SIZE( 60 );
604 else if( aLTFontSize == 5 ) return MILS_SIZE( 72 );
605 else if( aLTFontSize == 6 ) return MILS_SIZE( 88 );
606 else if( aLTFontSize == 7 ) return MILS_SIZE( 108 );
607 else return ToKicadFontSize( 2 );
608}
609
610
612{
613 return schIUScale.IUToMils( rescale( 16, aCoordinate, 50 ) );
614}
615
616
618 SCH_SHAPE* aShape )
619{
621 {
622 aShape->Rotate( VECTOR2I(), true );
623 }
625 {
626 aShape->Rotate( VECTOR2I(), false );
627 aShape->Rotate( VECTOR2I(), false );
628 }
630 {
631 aShape->Rotate( VECTOR2I(), false );
632 }
634 {
635 aShape->MirrorVertically( 0 );
636 }
638 {
639 aShape->MirrorVertically( 0 );
640 aShape->Rotate( VECTOR2I(), false );
641 }
643 {
644 aShape->MirrorHorizontally( 0 );
645 }
647 {
648 aShape->MirrorVertically( 0 );
649 aShape->Rotate( VECTOR2I(), true );
650 }
651}
652
653
655 SCH_SYMBOL* aSchSymbol )
656{
658 {
659 aSchSymbol->SetOrientation( SYM_ORIENT_0 );
660 }
662 {
663 aSchSymbol->SetOrientation( SYM_ORIENT_180 );
665 }
667 {
668 aSchSymbol->SetOrientation( SYM_ORIENT_180 );
669 }
671 {
673 }
675 {
676 aSchSymbol->SetOrientation( SYM_MIRROR_Y );
677 }
679 {
680 aSchSymbol->SetOrientation( SYM_MIRROR_Y );
682 }
684 {
685 aSchSymbol->SetOrientation( SYM_MIRROR_X );
686 }
688 {
689 aSchSymbol->SetOrientation( SYM_MIRROR_Y );
691 }
692}
693
694
696 SCH_SHEET_PATH* aSheet )
697{
698 SCH_LINE* segment = new SCH_LINE();
699
702
703 segment->SetStartPoint( aLTSymbol.Wires[aIndex].Start );
704 segment->SetEndPoint( aLTSymbol.Wires[aIndex].End );
705
706 aSheet->LastScreen()->Append( segment );
707}
708
709
711 std::vector<LTSPICE_SCHEMATIC::LT_ASC>& outLT_ASCs )
712{
713 SCH_SCREEN* screen = aSheet->LastScreen();
714
715 for( LTSPICE_SCHEMATIC::LT_ASC& lt_asc : outLT_ASCs )
716 {
717 for( int j = 0; j < (int) lt_asc.Lines.size(); j++ )
718 CreateLine( lt_asc, j, aSheet );
719
720 for( int j = 0; j < (int) lt_asc.Circles.size(); j++ )
721 CreateCircle( lt_asc, j, aSheet );
722
723 for( int j = 0; j < (int) lt_asc.Arcs.size(); j++ )
724 CreateArc( lt_asc, j, aSheet );
725
726 for( int j = 0; j < (int) lt_asc.Rectangles.size(); j++ )
727 CreateRect( lt_asc, j, aSheet );
728
729 for( int j = 0; j < (int) lt_asc.Bustap.size(); j++ )
730 CreateBusEntry( lt_asc, j, aSheet );
731
750
751 for( int j = 0; j < (int) lt_asc.Wires.size(); j++ )
752 CreateWire( lt_asc, j, aSheet, SCH_LAYER_ID::LAYER_WIRE );
753
754 for( int j = 0; j < (int) lt_asc.Iopins.size(); j++ )
755 CreatePin( lt_asc, j, aSheet );
756
757 for( const LTSPICE_SCHEMATIC::FLAG& lt_flag : lt_asc.Flags )
758 {
759 if( lt_flag.Value == wxS( "0" ) )
760 {
761 screen->Append( CreatePowerSymbol( lt_flag.Offset, lt_flag.Value, lt_flag.FontSize,
762 aSheet, lt_asc.Wires ) );
763 }
764 else
765 {
766 screen->Append( CreateSCH_LABEL( SCH_GLOBAL_LABEL_T, lt_flag.Offset, lt_flag.Value,
767 lt_flag.FontSize, lt_asc.Wires ) );
768 }
769 }
770
771 for( const LTSPICE_SCHEMATIC::TEXT& lt_text : lt_asc.Texts )
772 {
773 screen->Append( CreateSCH_TEXT( lt_text.Offset, convertLtSpiceTextToNgspice( lt_text.Value ),
774 lt_text.FontSize, lt_text.Justification ) );
775 }
776
777 for( const LTSPICE_SCHEMATIC::DATAFLAG& lt_flag : lt_asc.DataFlags )
778 {
780 lt_flag.Expression, lt_flag.FontSize, lt_asc.Wires ) );
781 }
782 }
783}
784
785
787 SCH_SHEET_PATH* aSheet )
788{
789 LTSPICE_SCHEMATIC::BUSTAP& bustap = aAscfile.Bustap[aIndex];
790
791 for( int k = 0; k < (int) aAscfile.Wires.size(); k++ )
792 {
793 if( ( aAscfile.Wires[k].Start == bustap.Start )
794 || ( aAscfile.Wires[k].End == bustap.Start ) )
795 {
796 CreateWire( aAscfile, k, aSheet, SCH_LAYER_ID::LAYER_BUS );
797 aAscfile.Wires.erase( aAscfile.Wires.begin() + k );
798 }
799 }
800
801 SCH_BUS_WIRE_ENTRY* busEntry = new SCH_BUS_WIRE_ENTRY( ToKicadCoords( { bustap.Start.x,
802 bustap.Start.y - 16 } ) );
803
804 busEntry->SetSize( { ToKicadCoords( 16 ), ToKicadCoords( 16 ) } );
805
806 aSheet->LastScreen()->Append( busEntry );
807}
808
809
819
820
822 SCH_SHEET_PATH* aSheet )
823{
824 LTSPICE_SCHEMATIC::IOPIN& iopin = aAscfile.Iopins[aIndex];
825 wxString ioPinName;
826
827 for( unsigned int k = 0; k < aAscfile.Flags.size(); k++ )
828 {
829 if( ( aAscfile.Flags[k].Offset.x == iopin.Location.x )
830 && ( aAscfile.Flags[k].Offset.y == iopin.Location.y ) )
831 {
832 ioPinName = aAscfile.Flags[k].Value;
833 aAscfile.Flags.erase( aAscfile.Flags.begin() + k );
834 }
835 }
836
837 SCH_HIERLABEL* sheetPin =
838 new SCH_HIERLABEL( ToKicadCoords( iopin.Location ), ioPinName, SCH_HIER_LABEL_T );
839
840 sheetPin->Move( m_originOffset );
841
842 sheetPin->SetShape( getLabelShape( iopin.Polarity ) );
843 aSheet->LastScreen()->Append( sheetPin );
844}
845
846
848 SCH_SHEET_PATH* aSheet )
849{
850 LTSPICE_SCHEMATIC::LINE& lt_line = aAscfile.Lines[aIndex];
852
853 line->SetEndPoint( ToKicadCoords( lt_line.End ) );
854 line->SetStroke( getStroke( lt_line.LineWidth, lt_line.LineStyle ) );
855 line->Move( m_originOffset );
856
857 aSheet->LastScreen()->Append( line );
858}
859
860
862 SCH_SHEET_PATH* aSheet )
863{
864 LTSPICE_SCHEMATIC::CIRCLE& lt_circle = aAscfile.Circles[aIndex];
866
867 VECTOR2I c = ( lt_circle.TopLeft + lt_circle.BotRight ) / 2;
868 int r = ( lt_circle.TopLeft.x - lt_circle.BotRight.x ) / 2;
869
870 circle->SetPosition( ToKicadCoords( c ) );
871 circle->SetEnd( ToKicadCoords( c ) + VECTOR2I( abs( ToKicadCoords( r ) ), 0 ) );
872 circle->SetStroke( getStroke( lt_circle.LineWidth, lt_circle.LineStyle ) );
873 circle->Move( m_originOffset );
874
875 aSheet->LastScreen()->Append( circle );
876}
877
878
880 SCH_SHEET_PATH* aSheet )
881{
882 LTSPICE_SCHEMATIC::ARC& lt_arc = aAscfile.Arcs[aIndex];
883 SCH_SHAPE* arc = new SCH_SHAPE( SHAPE_T::ARC );
884
885 arc->SetCenter( ToKicadCoords( ( lt_arc.TopLeft + lt_arc.BotRight ) / 2 ) );
886 arc->SetEnd( ToKicadCoords( lt_arc.ArcEnd ) );
887 arc->SetStart( ToKicadCoords( lt_arc.ArcStart ) );
888 arc->SetStroke( getStroke( lt_arc.LineWidth, lt_arc.LineStyle ) );
889 arc->Move( m_originOffset );
890
891 aSheet->LastScreen()->Append( arc );
892}
893
894
896 SCH_SHEET_PATH* aSheet )
897{
898 LTSPICE_SCHEMATIC::RECTANGLE& lt_rect = aAscfile.Rectangles[aIndex];
899 SCH_SHAPE* rectangle = new SCH_SHAPE( SHAPE_T::RECTANGLE );
900
901 rectangle->SetPosition( ToKicadCoords( lt_rect.TopLeft ) );
902 rectangle->SetEnd( ToKicadCoords( lt_rect.BotRight ) );
903 rectangle->SetStroke( getStroke( lt_rect.LineWidth, lt_rect.LineStyle ) );
904 rectangle->Move( m_originOffset );
905
906 aSheet->LastScreen()->Append( rectangle );
907}
908
909
911{
912 if( aLineWidth == LTSPICE_SCHEMATIC::LINEWIDTH::Normal )
913 return schIUScale.MilsToIU( 6 );
914 else if( aLineWidth == LTSPICE_SCHEMATIC::LINEWIDTH::Wide )
915 return schIUScale.MilsToIU( 12 );
916 else
917 return schIUScale.MilsToIU( 6 );
918}
919
920
933
934
936 const LTSPICE_SCHEMATIC::LINESTYLE& aLineStyle )
937{
938 return STROKE_PARAMS( getLineWidth( aLineWidth ), getLineStyle( aLineStyle ) );
939}
940
941
943 LTSPICE_SCHEMATIC::JUSTIFICATION aJustification )
944{
945 switch( aJustification )
946 {
948 aText->SetVisible( false );
949 break;
950
955 break;
956
961 break;
962
967 break;
968
973 break;
974
979 break;
980
981 default: break;
982 }
983
984 switch( aJustification )
985 {
992 break;
993
1000 break;
1001
1002 default: break;
1003 }
1004
1005 // Center, Left, Right aligns by first line in multiline text
1006 if( wxSplit( aText->GetText(), '\n', '\0' ).size() > 1 )
1007 {
1008 switch( aJustification )
1009 {
1014 aText->Offset( VECTOR2I( 0, -aText->GetTextHeight() / 2 ) );
1015 break;
1016
1021 aText->Offset( VECTOR2I( -aText->GetTextHeight() / 2, 0 ) );
1022 break;
1023
1024 default: break;
1025 }
1026 }
1027}
1028
1029
1030SCH_TEXT* SCH_IO_LTSPICE_PARSER::CreateSCH_TEXT( const VECTOR2I& aOffset, const wxString& aText,
1031 int aFontSize,
1032 LTSPICE_SCHEMATIC::JUSTIFICATION aJustification )
1033{
1034 VECTOR2I pos = ToKicadCoords( aOffset ) + m_originOffset;
1035 SCH_TEXT* textItem = new SCH_TEXT( pos, aText );
1036
1037 textItem->SetTextSize( ToKicadFontSize( aFontSize ) );
1038 textItem->SetVisible( true );
1039 textItem->SetMultilineAllowed( true );
1040
1041 setTextJustification( textItem, aJustification );
1042
1043 return textItem;
1044}
1045
1046
1048 SCH_SHEET_PATH* aSheet, SCH_LAYER_ID aLayer )
1049{
1050 SCH_LINE* segment = new SCH_LINE();
1051
1053 segment->SetLineStyle( LINE_STYLE::SOLID );
1054 segment->SetLayer( aLayer );
1055
1056 segment->SetStartPoint( ToKicadCoords( aAscfile.Wires[aIndex].Start ) + m_originOffset );
1057 segment->SetEndPoint( ToKicadCoords( aAscfile.Wires[aIndex].End ) + m_originOffset );
1058
1059 aSheet->LastScreen()->Append( segment );
1060}
1061
1062
1064 const wxString& aValue,
1065 int aFontSize, SCH_SHEET_PATH* aSheet,
1066 std::vector<LTSPICE_SCHEMATIC::WIRE>& aWires )
1067{
1068 LIB_SYMBOL* lib_symbol = new LIB_SYMBOL( wxS( "GND" ) );
1070
1071 shape->AddPoint( ToKicadCoords( { 16, 0 } ) );
1072 shape->AddPoint( ToKicadCoords( { -16, 0 } ) );
1073 shape->AddPoint( ToKicadCoords( { 0, 15 } ) );
1074 shape->AddPoint( ToKicadCoords( { 16, 0 } ) );
1075 shape->AddPoint( ToKicadCoords( { -16, 0 } ) );
1076 shape->AddPoint( ToKicadCoords( { 0, 15 } ) );
1077
1080
1081 lib_symbol->AddDrawItem( shape );
1082 lib_symbol->SetGlobalPower();
1083
1084 SCH_PIN* pin = new SCH_PIN( lib_symbol );
1085
1087 pin->SetPosition( ToKicadCoords( { 0, 0 } ) );
1088 pin->SetLength( 5 );
1089 pin->SetShape( GRAPHIC_PINSHAPE::LINE );
1090 lib_symbol->AddDrawItem( pin );
1091
1092 LIB_ID libId( wxS( "ltspice" ), wxS( "GND" ) );
1093 SCH_SYMBOL* sch_symbol = new SCH_SYMBOL( *lib_symbol, libId, aSheet, 1 );
1094
1095 sch_symbol->SetRef( aSheet, wxString::Format( wxS( "#GND%03d" ), m_powerSymbolIndex++ ) );
1096 sch_symbol->GetField( FIELD_T::REFERENCE )->SetVisible( false );
1097 sch_symbol->SetValueFieldText( wxS( "0" ) );
1098 sch_symbol->GetField( FIELD_T::VALUE )->SetTextSize( ToKicadFontSize( aFontSize ) );
1099 sch_symbol->GetField( FIELD_T::VALUE )->SetVisible( false );
1100
1101 sch_symbol->Move( ToKicadCoords( aOffset ) + m_originOffset );
1102
1103 for( LTSPICE_SCHEMATIC::WIRE& wire : aWires )
1104 {
1105 if( aOffset == wire.Start )
1106 {
1107 if( wire.Start.x == wire.End.x )
1108 {
1109 if( wire.Start.y < wire.End.y )
1110 {
1113 }
1114 }
1115 else
1116 {
1117 if( wire.Start.x < wire.End.x )
1118 sch_symbol->SetOrientation( SYM_ROTATE_CLOCKWISE );
1119 else if( wire.Start.x > wire.End.x )
1121 }
1122 }
1123 else if( aOffset == wire.End )
1124 {
1125 if( wire.Start.x == wire.End.x )
1126 {
1127 if( wire.Start.y > wire.End.y )
1128 {
1131 }
1132 }
1133 else
1134 {
1135 if( wire.Start.x < wire.End.x )
1137 else if( wire.Start.x > wire.End.x )
1138 sch_symbol->SetOrientation( SYM_ROTATE_CLOCKWISE );
1139 }
1140 }
1141 }
1142
1143 return sch_symbol;
1144}
1145
1146
1149 const wxString& aValue, int aFontSize,
1150 std::vector<LTSPICE_SCHEMATIC::WIRE>& aWires )
1151{
1152 SCH_LABEL_BASE* label = nullptr;
1153
1154 if( aType == SCH_GLOBAL_LABEL_T )
1155 {
1156 label = new SCH_GLOBALLABEL();
1157
1158 label->SetText( aValue );
1159 label->SetTextSize( ToKicadFontSize( aFontSize ) );
1160 label->SetSpinStyle( SPIN_STYLE::UP );
1161 }
1162 else if( aType == SCH_DIRECTIVE_LABEL_T )
1163 {
1164 label = new SCH_DIRECTIVE_LABEL();
1165
1167
1168 SCH_FIELD field( label, FIELD_T::USER, wxS( "DATAFLAG" ) );
1169 field.SetText( aValue );
1170 field.SetTextSize( ToKicadFontSize( aFontSize ) );
1171 field.SetVisible( true );
1172
1173 label->AddField( field );
1174 label->AutoplaceFields( nullptr, AUTOPLACE_AUTO );
1175 }
1176 else
1177 {
1178 UNIMPLEMENTED_FOR( wxString::Format( wxT( "Type not supported %d" ), (int)aType ) );
1179 }
1180
1181 if( label )
1182 {
1183 label->SetPosition( ToKicadCoords( aOffset ) + m_originOffset );
1184 label->SetVisible( true );
1185 }
1186
1187 std::vector<SPIN_STYLE> preferredSpins;
1188
1189 for( LTSPICE_SCHEMATIC::WIRE& wire : aWires )
1190 {
1191 if( aOffset == wire.Start )
1192 {
1193 if( wire.Start.x == wire.End.x )
1194 {
1195 if( wire.Start.y < wire.End.y )
1196 preferredSpins.emplace_back( SPIN_STYLE::UP );
1197 else if( wire.Start.y > wire.End.y )
1198 preferredSpins.emplace_back( SPIN_STYLE::BOTTOM );
1199 }
1200 else
1201 {
1202 if( wire.Start.x < wire.End.x )
1203 preferredSpins.emplace_back( SPIN_STYLE::LEFT );
1204 else if( wire.Start.x > wire.End.x )
1205 preferredSpins.emplace_back( SPIN_STYLE::RIGHT );
1206 }
1207 }
1208 else if( aOffset == wire.End )
1209 {
1210 if( wire.Start.x == wire.End.x )
1211 {
1212 if( wire.Start.y > wire.End.y )
1213 preferredSpins.emplace_back( SPIN_STYLE::UP );
1214 else if( wire.Start.y < wire.End.y )
1215 preferredSpins.emplace_back( SPIN_STYLE::BOTTOM );
1216 }
1217 else
1218 {
1219 if( wire.Start.x > wire.End.x )
1220 preferredSpins.emplace_back( SPIN_STYLE::LEFT );
1221 else if( wire.Start.x < wire.End.x )
1222 preferredSpins.emplace_back( SPIN_STYLE::RIGHT );
1223 }
1224 }
1225 }
1226
1227 if( preferredSpins.size() == 1 )
1228 label->SetSpinStyle( preferredSpins.front() );
1229
1230 return label;
1231}
1232
1233
1235 SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheet )
1236{
1237 wxString symbolName = aLTSymbol.Name.Upper();
1238 wxString type = aLTSymbol.SymAttributes[wxS( "TYPE" )].Upper();
1239 wxString prefix = aLTSymbol.SymAttributes[wxS( "PREFIX" )].Upper();
1240 wxString instName = aLTSymbol.SymAttributes[wxS( "INSTNAME" )].Upper();
1241 wxString value = aLTSymbol.SymAttributes[wxS( "VALUE" )];
1242 wxString value2 = aLTSymbol.SymAttributes[wxS( "VALUE2" )];
1243
1244 if( value.IsEmpty() )
1245 {
1246 value = value2;
1247 value2 = wxEmptyString;
1248 }
1249
1250 auto addField =
1251 [&]( const wxString& aFieldName, const wxString& aFieldValue )
1252 {
1253 SCH_FIELD newField( aSymbol, FIELD_T::USER, aFieldName );
1254 newField.SetVisible( false );
1255 newField.SetText( aFieldValue );
1256 aSymbol->AddField( newField );
1257 };
1258
1259
1260 auto setupNonInferredPassive =
1261 [&]( const wxString& aDevice, const wxString& aValueKey )
1262 {
1263 addField( wxS( "Sim.Device" ), aDevice );
1264 addField( wxS( "Sim.Params" ), aValueKey + wxS( "=${VALUE}" ) );
1265 };
1266
1267 auto setupBehavioral =
1268 [&]( const wxString& aDevice, const wxString& aType )
1269 {
1270 aSymbol->SetValueFieldText( wxS( "${Sim.Params}" ) );
1271
1272 addField( wxS( "Sim.Device" ), aDevice );
1273 addField( wxS( "Sim.Type" ), aType );
1274 addField( wxS( "Sim.Params" ), value );
1275 };
1276
1277 static const std::set<wxString> prefixWithGain = { wxS( "E" ), wxS( "F" ), wxS( "G" ), wxS( "H" ) };
1278
1279 if( prefix == wxS( "R" ) )
1280 {
1281 setupNonInferredPassive( prefix, wxS( "R" ) );
1282 }
1283 else if( prefix == wxS( "C" ) )
1284 {
1285 setupNonInferredPassive( prefix, wxS( "C" ) );
1286 }
1287 else if( prefix == wxS( "L" ) )
1288 {
1289 setupNonInferredPassive( prefix, wxS( "L" ) );
1290 }
1291 else if( prefixWithGain.count( prefix ) > 0 )
1292 {
1293 setupNonInferredPassive( prefix, wxS( "gain" ) );
1294 }
1295 else if( prefix == wxS( "B" ) )
1296 {
1297 if( symbolName.StartsWith( wxS( "BV" ) ) )
1298 setupBehavioral( wxS( "V" ), wxS( "=" ) );
1299 else if( symbolName.StartsWith( wxS( "BI" ) ) )
1300 setupBehavioral( wxS( "I" ), wxS( "=" ) );
1301 }
1302 else if( prefix == wxS( "T" ) )
1303 {
1304 aSymbol->SetValueFieldText( wxS( "${Sim.Params}" ) );
1305
1306 addField( wxS( "Sim.Device" ), wxS( "TLINE" ) );
1307 addField( wxS( "Sim.Params" ), value );
1308 }
1309 else if( prefix == wxS( "V" ) || symbolName == wxS( "I" ) )
1310 {
1311 addField( wxS( "Sim.Device" ), wxS( "SPICE" ) );
1312
1313 wxString simParams;
1314 wxString pwlArgs;
1315 wxString upperValue = value.Upper();
1316
1317 if( upperValue.StartsWith( wxS( "PWL " ) ) && upperValue.Contains( wxS( "FILE=" ) ) )
1318 {
1319 // TODO: support REPEAT statements
1320
1321 // Take the arguments from the original text so the data file path keeps its case
1322 pwlArgs = value.Mid( 4 );
1323
1324 if( !value2.IsEmpty() )
1325 pwlArgs << wxS( " " ) << value2;
1326
1327 pwlArgs.Trim( true ).Trim( false );
1328
1329 std::vector<wxString> ltspiceArgs = tokenizeQuoted( pwlArgs );
1330 std::vector<wxString> ngspiceArgs;
1331 wxString fileRef;
1332
1333 for( wxString& arg : ltspiceArgs )
1334 {
1335 wxString argValue;
1336 wxString argKey = arg.BeforeFirst( '=', &argValue );
1337
1338 // Unquote the arg value
1339 if( argValue.length() >= 2 && argValue.StartsWith( wxS( "\"" ) ) && argValue.EndsWith( wxS( "\"" ) ) )
1340 argValue = argValue.Mid( 1, argValue.length() - 2 );
1341
1342 if( argKey.Upper() == wxS( "FILE" ) )
1343 {
1344 wxString fileValue = argValue;
1345
1346 if( fileValue.IsEmpty() )
1347 continue;
1348
1349 // Convert the data file to ngspice format
1350 wxFileName sourceFile( fileValue );
1351
1352 wxString sanitizedName = sourceFile.GetName();
1353 sanitizedName.MakeLower();
1354 sanitizedName.Replace( wxS( " " ), wxS( "_" ) );
1355
1356 wxFileName convertedFile = sourceFile;
1357 convertedFile.SetName( sanitizedName + wxS( "_ngspice" ) );
1358 convertedFile.SetExt( sourceFile.GetExt().Lower() );
1359
1360 if( sourceFile.FileExists() )
1361 {
1362 if( !convertPwlFileToNgspice( sourceFile, convertedFile ) )
1363 {
1364 wxLogWarning( wxS( "Failed to convert PWL data file to ngspice format: " )
1365 + sourceFile.GetFullPath() );
1366 }
1367 }
1368
1369 // Avoid \\ escape issues in Sim.Params quoted values.
1370 fileRef = convertedFile.GetFullPath();
1371 fileRef.Replace( wxS( "\\" ), wxS( "/" ) );
1372 }
1373 }
1374
1375 // Use a subcircuit instance for the PWL data file
1376 prefix = "X";
1377 value2 = "";
1378 value = wxS( "pwl_file file=\\\"" ) + fileRef + wxS( "\\\" timerelative=1" );
1379 }
1380
1381 simParams << "type=" << '"' << prefix << '"' << ' ';
1382
1383 if( value2.IsEmpty() )
1384 simParams << "model=" << '"' << "${VALUE}" << '"' << ' ';
1385 else
1386 simParams << "model=" << '"' << "${VALUE} ${VALUE2}" << '"' << ' ';
1387
1388 addField( wxS( "Sim.Params" ), simParams );
1389 }
1390 else
1391 {
1392 wxString libFile = aLTSymbol.SymAttributes[wxS( "MODELFILE" )];
1393
1394 if( prefix == wxS( "X" ) )
1395 {
1396 // A prefix of X overrides the simulation model for other symbols (npn, etc.)
1397 type = wxS( "X" );
1398 }
1399 else if( libFile.IsEmpty() )
1400 {
1401 if( type.IsEmpty() )
1402 type = symbolName;
1403 }
1404
1405 if( !libFile.IsEmpty() )
1406 {
1407 addField( wxS( "Sim.Library" ), libFile );
1408 addField( wxS( "Sim.Name" ), symbolName );
1409 }
1410
1411 wxString spiceLine = aLTSymbol.SymAttributes[wxS( "SPICELINE" )];
1412
1413 if( type == wxS( "X" ) )
1414 {
1415 addField( wxS( "Sim.Device" ), wxS( "SUBCKT" ) );
1416
1417 if( !spiceLine.IsEmpty() )
1418 addField( wxS( "Sim.Params" ), spiceLine );
1419 }
1420 else
1421 {
1422 addField( wxS( "Sim.Device" ), wxS( "SPICE" ) );
1423
1424 if( !spiceLine.IsEmpty() )
1425 addField( wxS( "Sim.Params" ), spiceLine );
1426 else
1427 addField( wxS( "Sim.Params" ), "model=\"" + value + "\"" );
1428 }
1429 }
1430
1431 // Set this at the end, as we may have changed the variables
1432 aSymbol->SetRef( aSheet, instName );
1433 aSymbol->SetValueFieldText( value );
1434
1435 if( !value2.IsEmpty() )
1436 addField( wxS( "Value2" ), value2 );
1437
1438 for( LTSPICE_SCHEMATIC::LT_WINDOW& lt_window : aLTSymbol.Windows )
1439 {
1440 SCH_FIELD* field = nullptr;
1441
1442 switch( lt_window.WindowNumber )
1443 {
1444 case -1: /* PartNum */ break;
1445 case 0: /* InstName */ field = aSymbol->GetField( FIELD_T::REFERENCE ); break;
1446 case 1: /* Type */ break;
1447 case 2: /* RefName */ break;
1448 case 3: /* Value */ field = aSymbol->GetField( FIELD_T::VALUE ); break;
1449
1450 case 5: /* QArea */ break;
1451
1452 case 8: /* Width */ break;
1453 case 9: /* Length */ break;
1454 case 10: /* Multi */ break;
1455
1456 case 16: /* Nec */ break;
1457
1458 case 38: /* SpiceModel */ field = aSymbol->GetField( wxS( "Sim.Name" ) ); break;
1459 case 39: /* SpiceLine */ field = aSymbol->GetField( wxS( "Sim.Params" ) ); break;
1460 case 40: /* SpiceLine2 */ break;
1461
1462 /*
1463 47 Def_Sub
1464
1465 50 Digital_Timing_Model
1466 51 Digital_Extracts
1467 52 Digital_IO_Model
1468 53 Digital_Line
1469 54 Digital_Primitive
1470 55 Digital_MNTYMXDLY
1471 56 Digital_IO_LEVEL
1472 57 Digital_StdCell
1473 58 Digital_File
1474
1475 105 Cell
1476 106 W/L
1477 107 PSIZE
1478 108 NSIZE
1479 109 sheets
1480 110 sh#
1481 111 Em_Scale
1482 112 Epi
1483 113 Sinker
1484 114 Multi5
1485
1486 118 AQ
1487 119 AQSUB
1488 120 ZSIZE
1489 121 ESR
1490 123 Value2
1491 124 COUPLE
1492 125 Voltage
1493 126 Area1
1494 127 Area2
1495 128 Area3
1496 129 Area4
1497 130 Multi1
1498 131 Multi2
1499 132 Multi3
1500 133 Multi4
1501 134 DArea
1502 135 DPerim
1503 136 CArea
1504 137 CPerim
1505 138 Shrink
1506 139 Gate_Resize
1507
1508 142 BP
1509 143 BN
1510 144 Sim_Level
1511
1512 146 G_Voltage
1513
1514 150 SpiceLine3
1515
1516 153 D_VOLTAGES
1517
1518 156 Version
1519 157 Comment
1520 158 XDef_Sub
1521 159 LVS_Area
1522
1523 162 User1
1524 163 User2
1525 164 User3
1526 165 User4
1527 166 User5
1528 167 Root
1529 168 Class
1530 169 Geometry
1531 170 WL_Delimiter
1532
1533 175 T1
1534 176 T2
1535
1536 184 DsgnName
1537 185 Designer
1538
1539 190 RTN
1540 191 PWR
1541 192 BW
1542
1543 201 CAPROWS
1544 202 CAPCOLS
1545 203 NF
1546 204 SLICES
1547 205 CUR
1548 206 TEMPRISE
1549 207 STRIPS
1550 208 WEM
1551 209 LEM
1552 210 BASES
1553 211 COLS
1554 212 XDef_Tub
1555 */
1556 default: break;
1557 }
1558
1559 if( field )
1560 {
1561 field->SetPosition( ToKicadCoords( lt_window.Position ) );
1562 field->SetTextSize( ToKicadFontSize( lt_window.FontSize ) );
1563
1564 if( lt_window.FontSize == 0 )
1565 field->SetVisible( false );
1566
1567 setTextJustification( field, lt_window.Justification );
1568 }
1569 }
1570}
1571
1572
1574 SCH_SHAPE* aRectangle )
1575{
1576 LTSPICE_SCHEMATIC::RECTANGLE& lt_rect = aLTSymbol.Rectangles[aIndex];
1577
1578 aRectangle->SetPosition( ToKicadCoords( lt_rect.BotRight ) );
1579 aRectangle->SetEnd( ToKicadCoords( lt_rect.TopLeft ) );
1580 aRectangle->SetStroke( getStroke( lt_rect.LineWidth, lt_rect.LineStyle ) );
1581
1582 if( aLTSymbol.SymAttributes[wxS( "Prefix" )] == wxS( "X" ) )
1584}
1585
1586
1588 SCH_SHEET_PATH* aSheet )
1589{
1590 LTSPICE_SCHEMATIC::RECTANGLE& lt_rect = aLTSymbol.Rectangles[aIndex];
1591 SCH_SHAPE* rectangle = new SCH_SHAPE( SHAPE_T::RECTANGLE );
1592
1593 rectangle->SetPosition( ToKicadCoords( lt_rect.BotRight ) );
1594 rectangle->SetEnd( ToKicadCoords( lt_rect.TopLeft ) );
1595 rectangle->SetStroke( getStroke( lt_rect.LineWidth, lt_rect.LineStyle ) );
1596
1597 rectangle->Move( aLTSymbol.Offset );
1598 RotateMirrorShape( aLTSymbol, rectangle );
1599
1600 aSheet->LastScreen()->Append( rectangle );
1601}
1602
1603
1605 SCH_PIN* aPin )
1606{
1607 LTSPICE_SCHEMATIC::LT_PIN& lt_pin = aLTSymbol.Pins[aIndex];
1608 wxString device = aLTSymbol.Name.Lower();
1609
1610 if( aLTSymbol.Pins.size() == 2 && ( device == wxS( "res" )
1611 || device == wxS( "cap" )
1612 || device == wxS( "ind" ) ) )
1613 {
1614 // drop A/B pin names from simple LRCs as they're not terribly useful (and prevent
1615 // other pin names on the net from driving the net name).
1616 }
1617 else
1618 {
1619 aPin->SetName( lt_pin.PinAttribute[ wxS( "PinName" ) ] );
1620
1622 aPin->SetNameTextSize( 0 );
1623 }
1624
1625 aPin->SetNumber( wxString::Format( wxS( "%d" ), aIndex + 1 ) );
1626
1627 // Prefer LTspice SpiceOrder for pin numbers
1628 wxString spiceOrder = lt_pin.PinAttribute[ wxS( "SpiceOrder" ) ];
1629 long spiceOrderNum = 0;
1630
1631 if( spiceOrder.ToLong( &spiceOrderNum ) && spiceOrderNum > 0 )
1632 aPin->SetNumber( wxString::Format( wxS( "%ld" ), spiceOrderNum ) );
1633
1635 aPin->SetPosition( ToKicadCoords( lt_pin.PinLocation ) );
1636 aPin->SetLength( 5 );
1638
1639 switch( lt_pin.PinJustification )
1640 {
1644 break;
1645
1649 break;
1650
1654 break;
1655
1659 break;
1660
1661 default: break;
1662 }
1663}
1664
1665
1667 SCH_SHAPE* aArc )
1668{
1669 LTSPICE_SCHEMATIC::ARC& lt_arc = aLTSymbol.Arcs[aIndex];
1670
1671 aArc->SetCenter( ToKicadCoords( ( lt_arc.TopLeft + lt_arc.BotRight ) / 2 ) );
1672 aArc->SetStart( ToKicadCoords( lt_arc.ArcEnd ) );
1673 aArc->SetEnd( ToKicadCoords( lt_arc.ArcStart ) );
1674 aArc->SetStroke( getStroke( lt_arc.LineWidth, lt_arc.LineStyle ) );
1675}
1676
1677
1679 SCH_SHEET_PATH* aSheet )
1680{
1681 LTSPICE_SCHEMATIC::ARC& lt_arc = aLTSymbol.Arcs[aIndex];
1682 SCH_SHAPE* arc = new SCH_SHAPE( SHAPE_T::ARC );
1683
1684 arc->SetCenter( ToKicadCoords( ( lt_arc.TopLeft + lt_arc.BotRight ) / 2 ) );
1685 arc->SetStart( ToKicadCoords( lt_arc.ArcEnd ) );
1686 arc->SetEnd( ToKicadCoords( lt_arc.ArcStart ) );
1687 arc->SetStroke( getStroke( lt_arc.LineWidth, lt_arc.LineStyle ) );
1688
1689 arc->Move( ToKicadCoords( aLTSymbol.Offset ) + m_originOffset );
1690 RotateMirrorShape( aLTSymbol, arc );
1691
1692 aSheet->LastScreen()->Append( arc );
1693}
1694
1695
1697 SCH_SHEET_PATH* aSheet )
1698{
1699 LTSPICE_SCHEMATIC::CIRCLE& lt_circle = aLTSymbol.Circles[aIndex];
1701
1702 VECTOR2I c = ( lt_circle.TopLeft + lt_circle.BotRight ) / 2;
1703 int r = ( lt_circle.TopLeft.x - lt_circle.BotRight.x ) / 2;
1704
1705 circle->SetPosition( ToKicadCoords( c ) );
1706 circle->SetEnd( ToKicadCoords( c ) + VECTOR2I( abs( ToKicadCoords( r ) ), 0 ) );
1707 circle->SetStroke( getStroke( lt_circle.LineWidth, lt_circle.LineStyle ) );
1708
1709 circle->Move( aLTSymbol.Offset );
1710 RotateMirrorShape( aLTSymbol, circle );
1711
1712 aSheet->LastScreen()->Append( circle );
1713}
1714
1715
1717 SCH_SHAPE* aCircle )
1718{
1719 LTSPICE_SCHEMATIC::CIRCLE& lt_circle = aLTSymbol.Circles[aIndex];
1720
1721 VECTOR2I c = ( lt_circle.TopLeft + lt_circle.BotRight ) / 2;
1722 int r = ( lt_circle.TopLeft.x - lt_circle.BotRight.x ) / 2;
1723
1724 aCircle->SetPosition( ToKicadCoords( c ) );
1725 aCircle->SetEnd( ToKicadCoords( c ) + VECTOR2I( abs( ToKicadCoords( r ) ), 0 ) );
1726 aCircle->SetStroke( getStroke( lt_circle.LineWidth, lt_circle.LineStyle ) );
1727}
1728
1729
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
constexpr void SetOrigin(const Vec &pos)
Definition box2.h:234
constexpr size_type GetWidth() const
Definition box2.h:211
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:653
constexpr const Vec GetCenter() const
Definition box2.h:227
constexpr void SetSize(const SizeVec &size)
Definition box2.h:245
constexpr size_type GetHeight() const
Definition box2.h:212
constexpr coord_type GetLeft() const
Definition box2.h:225
constexpr const Vec & GetOrigin() const
Definition box2.h:207
constexpr const SizeVec & GetSize() const
Definition box2.h:203
constexpr coord_type GetTop() const
Definition box2.h:226
constexpr void Offset(coord_type dx, coord_type dy)
Definition box2.h:256
virtual void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:329
void SetCenter(const VECTOR2I &aCenter)
void SetFillMode(FILL_T aFill)
virtual void SetStart(const VECTOR2I &aStart)
Definition eda_shape.h:279
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
virtual void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:495
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
virtual int GetTextHeight() const
Definition eda_text.h:307
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition eda_text.cpp:373
virtual void Offset(const VECTOR2I &aOffset)
Definition eda_text.cpp:558
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:342
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:231
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition eda_text.cpp:263
void SetMultilineAllowed(bool aAllow)
Definition eda_text.cpp:357
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:365
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
Define a library symbol object.
Definition lib_symbol.h:119
void SetGlobalPower()
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition lib_symbol.h:321
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
POLARITY
Polarity enum represents polarity of pin.
JUSTIFICATION
Defines in what ways the PIN or TEXT can be justified.
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
Definition page_info.h:173
Holds all the data relating to one schematic.
Definition schematic.h:148
void SetSize(const VECTOR2I &aSize)
Class for a wire to bus entry.
void SetPosition(const VECTOR2I &aPosition) override
void SetText(const wxString &aText) override
int ToLtSpiceCoords(int aCoordinate)
Method converts kicad coordinate(i.e scale) to ltspice coordinates.
void CreateCircle(LTSPICE_SCHEMATIC::LT_ASC &aAscfile, int aIndex, SCH_SHEET_PATH *aSheet)
Method for plotting circle from Asc files.
void setTextJustification(EDA_TEXT *aText, LTSPICE_SCHEMATIC::JUSTIFICATION aJustification)
SCH_TEXT * CreateSCH_TEXT(const VECTOR2I &aOffset, const wxString &aText, int aFontSize, LTSPICE_SCHEMATIC::JUSTIFICATION aJustification)
Create schematic text.
void CreateWires(LTSPICE_SCHEMATIC::LT_SYMBOL &aLTSymbol, int aIndex, SCH_SHEET_PATH *aSheet)
Method for plotting wires.
void Parse(SCH_SHEET_PATH *aSheet, std::vector< LTSPICE_SCHEMATIC::LT_ASC > &outLT_ASCs, const std::vector< wxString > &aAsyFileNames)
Function responsible for loading the .asc and .asy files in intermediate data structure.
STROKE_PARAMS getStroke(const LTSPICE_SCHEMATIC::LINEWIDTH &aLineWidth, const LTSPICE_SCHEMATIC::LINESTYLE &aLineStyle)
void CreateKicadSYMBOLs(SCH_SHEET_PATH *aSheet, std::vector< LTSPICE_SCHEMATIC::LT_ASC > &outLT_ASCs, const std::vector< wxString > &aAsyFiles)
Main Method for loading indermediate data to kicacd object from asy files.
SCH_SYMBOL * CreatePowerSymbol(const VECTOR2I &aOffset, const wxString &aValue, int aFontSize, SCH_SHEET_PATH *aSheet, std::vector< LTSPICE_SCHEMATIC::WIRE > &aWires)
Create a power symbol.
void CreateLine(LTSPICE_SCHEMATIC::LT_ASC &aAscfile, int aIndex, SCH_SHEET_PATH *aSheet)
Method for plotting Line from Asc files.
int getLineWidth(const LTSPICE_SCHEMATIC::LINEWIDTH &aLineWidth)
void RotateMirror(LTSPICE_SCHEMATIC::LT_SYMBOL &aLTSymbol, SCH_SYMBOL *aSchSymbol)
Methods for rotating and mirroring objects.
void CreateBusEntry(LTSPICE_SCHEMATIC::LT_ASC &aAscfile, int aIndex, SCH_SHEET_PATH *aSheet)
Method for plotting Bustap from Asc files.
void CreateRect(LTSPICE_SCHEMATIC::LT_ASC &aAscfile, int aIndex, SCH_SHEET_PATH *aSheet)
Method for plotting rectangle from Asc files.
void CreateWire(LTSPICE_SCHEMATIC::LT_ASC &aAscfile, int aIndex, SCH_SHEET_PATH *aSheet, SCH_LAYER_ID aLayer)
Create a schematic wire.
void CreateLines(LIB_SYMBOL *aSymbol, LTSPICE_SCHEMATIC::LT_SYMBOL &aLTSymbol, int aIndex, SCH_SHAPE *aShape)
Method for plotting Lines from Asy files.
void CreatePin(LTSPICE_SCHEMATIC::LT_ASC &aAscfile, int aIndex, SCH_SHEET_PATH *aSheet)
Method for plotting Iopin from Asc files.
void CreateArc(LTSPICE_SCHEMATIC::LT_ASC &aAscfile, int aIndex, SCH_SHEET_PATH *aSheet)
Method for plotting Arc from Asc files.
LINE_STYLE getLineStyle(const LTSPICE_SCHEMATIC::LINESTYLE &aLineStyle)
LTSPICE_SCHEMATIC * m_lt_schematic
int ToKicadCoords(int aCoordinate)
Method converts ltspice coordinate(i.e scale) to kicad coordinates.
void CreateFields(LTSPICE_SCHEMATIC::LT_SYMBOL &aLTSymbol, SCH_SYMBOL *aSymbol, SCH_SHEET_PATH *aSheet)
void RotateMirrorShape(LTSPICE_SCHEMATIC::LT_SYMBOL &aLTSymbol, SCH_SHAPE *aShape)
SCH_LABEL_BASE * CreateSCH_LABEL(KICAD_T aType, const VECTOR2I &aOffset, const wxString &aValue, int aFontSize, std::vector< LTSPICE_SCHEMATIC::WIRE > &aWires)
Create a label.
void CreateKicadSCH_ITEMs(SCH_SHEET_PATH *aSheet, std::vector< LTSPICE_SCHEMATIC::LT_ASC > &outLT_ASCs)
Main method for loading intermediate data structure from Asc file to kicad.
VECTOR2I ToKicadFontSize(int aLTFontSize)
void CreateSymbol(LTSPICE_SCHEMATIC::LT_SYMBOL &aLtSymbol, LIB_SYMBOL *aLibSymbol)
void SetLayer(SCH_LAYER_ID aLayer)
Definition sch_item.h:346
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
void AddField(const SCH_FIELD &aField)
Definition sch_label.h:228
void SetShape(LABEL_FLAG_SHAPE aShape)
Definition sch_label.h:179
void SetPosition(const VECTOR2I &aPosition) override
void AutoplaceFields(SCH_SCREEN *aScreen, AUTOPLACE_ALGO aAlgo) override
virtual void SetSpinStyle(SPIN_STYLE aSpinStyle)
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:39
void SetStartPoint(const VECTOR2I &aPosition)
Definition sch_line.h:137
void SetLineWidth(const int aSize)
Definition sch_line.cpp:437
void SetLineStyle(const LINE_STYLE aStyle)
Definition sch_line.cpp:408
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
Definition sch_line.cpp:247
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
Definition sch_line.h:199
void SetEndPoint(const VECTOR2I &aPosition)
Definition sch_line.h:146
void SetNumber(const wxString &aNumber)
Definition sch_pin.cpp:825
void SetOrientation(PIN_ORIENTATION aOrientation)
Definition sch_pin.h:111
void SetName(const wxString &aName)
Definition sch_pin.cpp:521
void SetPosition(const VECTOR2I &aPos) override
Definition sch_pin.h:314
void SetLength(int aLength)
Definition sch_pin.h:117
void SetShape(GRAPHIC_PINSHAPE aShape)
Definition sch_pin.h:114
void SetType(ELECTRICAL_PINTYPE aType)
Definition sch_pin.cpp:431
void SetNameTextSize(int aSize)
Definition sch_pin.cpp:853
const PAGE_INFO & GetPageSettings() const
Definition sch_screen.h:140
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
SCHEMATIC * Schematic() const
void SetPosition(const VECTOR2I &aPos) override
Definition sch_shape.h:87
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
void Move(const VECTOR2I &aOffset) override
Move the item by aMoveVector to a new position.
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition sch_shape.cpp:97
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
void AddPoint(const VECTOR2I &aPosition)
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
SCH_SCREEN * LastScreen()
Schematic symbol object.
Definition sch_symbol.h:75
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
Definition sch_symbol.h:830
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
void SetOrientation(int aOrientation)
Compute the new transform matrix based on aOrientation for the symbol which is applied to the current...
void SetValueFieldText(const wxString &aValue, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString)
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
Helper class to recognize Spice formatted values.
Definition spice_value.h:52
wxString ToSpiceString() const
Return string value in Spice format (e.g.
double ToDouble() const
Simple container to manage line stroke parameters.
virtual void SetShowPinNumbers(bool aShow)
Set or clear the pin number visibility flag.
Definition symbol.h:170
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition eda_angle.h:419
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition eda_angle.h:418
@ FILLED_WITH_BG_BODYCOLOR
Definition eda_fill.h:32
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:57
SCH_LAYER_ID
Eeschema drawing layers.
Definition layer_ids.h:471
@ LAYER_DEVICE
Definition layer_ids.h:488
@ LAYER_WIRE
Definition layer_ids.h:474
@ LAYER_NOTES
Definition layer_ids.h:489
@ LAYER_BUS
Definition layer_ids.h:475
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:92
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:96
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
Definition pin_type.h:42
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
Definition pin_type.h:39
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
Definition pin_type.h:123
@ PIN_RIGHT
The pin extends rightwards from the connection point.
Definition pin_type.h:107
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
Definition pin_type.h:114
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
Definition pin_type.h:131
static wxString convertLtSpiceTextToNgspice(const wxString &aText)
static std::vector< wxString > tokenizeQuoted(const wxString &aText)
Parses the datastructure produced by the LTSPICE_SCHEMATIC into a KiCad schematic file.
static bool convertPwlFileToNgspice(const wxFileName &aSourceFile, const wxFileName &aDestFile)
LABEL_FLAG_SHAPE getLabelShape(LTSPICE_SCHEMATIC::POLARITY aPolarity)
@ AUTOPLACE_AUTO
Definition sch_item.h:70
LABEL_FLAG_SHAPE
Definition sch_label.h:97
@ L_BIDI
Definition sch_label.h:100
@ L_OUTPUT
Definition sch_label.h:99
@ L_INPUT
Definition sch_label.h:98
LINE_STYLE
Dashed line types.
The ARC is represented inside a rectangle whose opposite site are given.
The CIRCLE is represented in Ltpsice inside a rectangle whose two opposite points and line style are ...
IOPIN is special contact on symbol used for IO operations.
A struct to hold .asc file definition.
std::vector< CIRCLE > Circles
std::vector< IOPIN > Iopins
std::vector< BUSTAP > Bustap
std::vector< RECTANGLE > Rectangles
std::map< wxString, wxString > PinAttribute
A struct to hold SYMBOL definition.
std::map< wxString, wxString > SymAttributes
std::vector< RECTANGLE > Rectangles
std::vector< LT_WINDOW > Windows
std::vector< CIRCLE > Circles
A 4-sided polygon with opposite equal sides, used in representing shapes.
A metallic connection, used for transfer, between two points or pin.
@ SYM_ROTATE_CLOCKWISE
Definition symbol.h:33
@ SYM_ROTATE_COUNTERCLOCKWISE
Definition symbol.h:34
@ SYM_MIRROR_Y
Definition symbol.h:40
@ SYM_ORIENT_180
Definition symbol.h:37
@ SYM_MIRROR_X
Definition symbol.h:39
@ SYM_ORIENT_0
Definition symbol.h:35
@ USER
The field ID hasn't been set yet; field is invalid.
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
KIBIS_PIN * pin
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:167
@ SCH_HIER_LABEL_T
Definition typeinfo.h:165
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:164
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).
Definition util.h:135
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683