1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2020-2021 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
5  * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * 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 
21 /**
22  * @file cadstar_pcb_archive_parser.cpp
23  * @brief Reads in a CADSTAR Schematic Archive (*.csa) file
24  */
25 
26 #ifndef CADSTAR_SCH_ARCHIVE_PARSER_H_
27 #define CADSTAR_SCH_ARCHIVE_PARSER_H_
28 
29 #include <plugins/cadstar/cadstar_archive_parser.h>
30 
31 
32 /**
33  * @brief Represents a CADSTAR Schematic Archive (*.csa) file
34  */
35 class CADSTAR_SCH_ARCHIVE_PARSER : public CADSTAR_ARCHIVE_PARSER
36 {
37 public:
CADSTAR_SCH_ARCHIVE_PARSER(wxString aFilename)38     explicit CADSTAR_SCH_ARCHIVE_PARSER( wxString aFilename )
39             : CADSTAR_ARCHIVE_PARSER(), Filename( aFilename ), Header(), Assignments(), KiCadUnitDivider( 10 )
40     {
41     }
42 
43     /**
44      * @brief Parses the file
45      * @throw IO_ERROR if file could not be opened or there was
46      * an error while parsing
47      */
48     void Parse();
49 
50 
51     typedef wxString TERMINALCODE_ID;
52     typedef wxString SYMBOL_ID;
53     typedef wxString BUS_ID;
54     typedef wxString BLOCK_ID;
55     typedef wxString SHEET_NAME;
56 
57 
58     enum class TERMINAL_SHAPE_TYPE
59     {
60         ANNULUS,
61         BOX,
62         BULLET,
63         CIRCLE, ///< Keyword "ROUND"
64         CROSS,
65         DIAMOND,
66         FINGER,
67         OCTAGON,
68         PLUS,
69         POINTER,
70         RECTANGLE,
71         ROUNDED_RECT, ///< Keyword "ROUNDED"
72         SQUARE,
73         STAR,
74         TRIANGLE,
75         UNDEFINED ///< Only used for error checking (not a real shape)
76     };
77 
78 
79     static TERMINAL_SHAPE_TYPE ParseTermShapeType( const wxString& aShapeStr );
80 
81 
82     struct TERMINAL_SHAPE : PARSER
83     {
84         TERMINAL_SHAPE_TYPE ShapeType;
85         long                Size            = UNDEFINED_VALUE;
86         // Note in the CADSTAR GUI, it only talks about "length", but the file seems to
87         // split it in "left length" and "right length" (similar to PADCODE in the PCB)
88         // for some terminal shapes such as RECTANGLE but not for others, such as TRIANGLE
89         long                LeftLength      = UNDEFINED_VALUE; ///< Might also be total length
90         long                RightLength     = UNDEFINED_VALUE; ///< Could be blank
91         long                InternalFeature = UNDEFINED_VALUE;
92         long                OrientAngle     = 0; ///< 1/1000 of a Degree
93 
94         static bool IsTermShape( XNODE* aNode );
95         void        Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
96     };
97 
98 
99     struct TERMINALCODE : PARSER
100     {
101         TERMINALCODE_ID ID;
102         wxString        Name;
103         TERMINAL_SHAPE  Shape;
104         bool            Filled = false;
105 
106         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
107     };
108 
109 
110     struct CODEDEFS_SCM : CADSTAR_ARCHIVE_PARSER::CODEDEFS
111     {
112         std::map<TERMINALCODE_ID, TERMINALCODE> TerminalCodes;
113 
114         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
115     };
116 
117 
118     struct ASSIGNMENTS_SCM : PARSER
119     {
120         CODEDEFS_SCM Codedefs;
121         GRIDS        Grids;
122         SETTINGS     Settings;
123         bool         NetclassEditAttributeSettings     = false; //< Unclear what this does
124         bool         SpacingclassEditAttributeSettings = false; //< Unclear what this does
125 
126         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
127     };
128 
129 
130     struct TERMINAL : PARSER
131     {
132         TERMINAL_ID     ID;
133         TERMINALCODE_ID TerminalCodeID;
134         POINT           Position; ///< Pad position within the component's coordinate frame.
135         long            OrientAngle = 0;
136 
137         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
138     };
139 
140 
141     struct PIN_NUM_LABEL_LOC : CADSTAR_ARCHIVE_PARSER::ATTRIBUTE_LOCATION
142     {
143         TERMINAL_ID TerminalID;
144 
145         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
146     };
147 
148 
149     struct SYMDEF_SCM : CADSTAR_ARCHIVE_PARSER::SYMDEF
150     {
151         std::map<TERMINAL_ID, TERMINAL>          Terminals;
152         std::map<TERMINAL_ID, PIN_NUM_LABEL_LOC> PinLabelLocations;
153         std::map<TERMINAL_ID, PIN_NUM_LABEL_LOC> PinNumberLocations;
154 
155 
156         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
157     };
158 
159 
160     struct LIBRARY_SCM : PARSER
161     {
162         std::map<SYMDEF_ID, SYMDEF_SCM> SymbolDefinitions;
163 
164         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
165     };
166 
167 
168     struct SHEETS : PARSER
169     {
170         std::map<LAYER_ID, SHEET_NAME> SheetNames;
171         std::vector<LAYER_ID>          SheetOrder; ///< A vector to also store the order in which
172                                                    ///< sheets are to be displayed
173 
174         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
175     };
176 
177 
178     struct COMP : PARSER
179     {
180         wxString           Designator  = wxEmptyString;
181         bool               ReadOnly    = false;
182         bool               HasLocation = false;
183         ATTRIBUTE_LOCATION AttrLoc;
184 
185         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
186     };
187 
188 
189     struct PARTREF : PARSER
190     {
191         PART_ID            RefID       = wxEmptyString;
192         bool               ReadOnly    = false;
193         bool               HasLocation = false;
194         ATTRIBUTE_LOCATION AttrLoc;
195 
196         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
197     };
198 
199 
200     struct TERMATTR : PARSER
201     {
202         TERMINAL_ID        TerminalID;
203         ATTRIBUTE_VALUE    Value;
204 
205         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
206     };
207 
208 
209     struct SYMPINNAME_LABEL : PARSER
210     {
211         TERMINAL_ID        TerminalID;
212         wxString           NameOrLabel;
213         bool               HasLocation = false;
214         ATTRIBUTE_LOCATION AttrLoc;
215 
216         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
217     };
218 
219 
220     struct SYMBOLVARIANT : PARSER
221     {
222         enum class TYPE
223         {
224             GLOBALSIGNAL,
225             SIGNALREF,
226             TESTPOINT
227             //TODO: there might be others
228         };
229 
230         TYPE     Type;
231         wxString Reference = wxEmptyString;
232 
233         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
234     };
235 
236 
237     struct SIGNALREFERENCELINK : CADSTAR_ARCHIVE_PARSER::ATTRIBUTE_LOCATION
238     {
239         wxString Text; ///< This contains the numbers of the other sheets where the
240                        ///< signal reference is present separated by commas
241 
242         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
243     };
244 
245 
246     struct SYMBOL : PARSER
247     {
248         struct PIN_NUM : PARSER
249         {
250             TERMINAL_ID        TerminalID;
251             long               PinNum;
252             bool               HasLocation = false;
253             ATTRIBUTE_LOCATION AttrLoc;
254 
255             void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
256         };
257 
258         SYMBOL_ID     ID;
259         SYMDEF_ID     SymdefID;
260         LAYER_ID      LayerID; ///< Sheet on which symbol is located
261         POINT         Origin;
262         GROUP_ID      GroupID = wxEmptyString; ///< If not empty, this symbol is part of a group
263         REUSEBLOCKREF ReuseBlockRef;
264         long          OrientAngle = 0;
265         bool          Mirror      = false;
266         bool          Fixed       = false;
267         long          ScaleRatioNumerator = 1; ///< Symbols can be arbitrarily scaled in CADSTAR
268         long          ScaleRatioDenominator = 1;
269         READABILITY   Readability = READABILITY::BOTTOM_TO_TOP;
270 
271         bool    IsComponent = false;
272         COMP    ComponentRef;
273         bool    HasPartRef = false;
274         PARTREF PartRef;
275         bool    PartNameVisible = true;
276         GATE_ID GateID; ///< The gate this symbol represents within the associated Part
277 
278         bool                IsSymbolVariant = false;
279         SYMBOLVARIANT       SymbolVariant;
280         SIGNALREFERENCELINK SigRefLink; ///< Signal References (a special form of global signal)
281                                         ///< have annotations showing the location of all the
282                                         ///< other sheets where the signal is present
283 
284         SYMBOL_ID  VariantParentSymbolID = wxEmptyString;
285         VARIANT_ID VariantID             = wxEmptyString;
286 
287         std::map<TERMINAL_ID, TERMATTR>         TerminalAttributes;
288         std::map<TERMINAL_ID, SYMPINNAME_LABEL> PinLabels;  ///< Equivalent to KiCad's Pin Name
289         std::map<TERMINAL_ID, SYMPINNAME_LABEL> PinNames;   ///< Identifier of the pin in the PCB
290                                                             ///< Equivalent to KiCad's Pin Number
291         std::map<TERMINAL_ID, PIN_NUM>          PinNumbers; ///< This seems to only appear in older
292                                                             ///< designs and is similar to PinNames
293                                                             ///< but only allowing numerical values
294         std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues;
295 
296         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
297     };
298 
299 
300     /**
301      * @brief Net name or bus name label
302      */
303     struct SIGLOC : CADSTAR_ARCHIVE_PARSER::ATTRIBUTE_LOCATION
304     {
305         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
306     };
307 
308 
309     struct BUS : PARSER
310     {
311         BUS_ID      ID;
312         LINECODE_ID LineCodeID;
313         LAYER_ID    LayerID; ///< Sheet on which bus is located
314         SHAPE       Shape;
315         wxString    Name        = wxEmptyString;
316         bool        HasBusLabel = false;
317         SIGLOC      BusLabel;
318 
319         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
320     };
321 
322 
323     struct BLOCK : PARSER
324     {
325         enum class TYPE
326         {
327             CLONE, ///< the block is referring to the sheet it is on.
328             PARENT,
329             CHILD
330         };
331 
332         BLOCK_ID ID;
333         TYPE     Type; ///< Determines what the associated layer is, whether parent, child or clone
334         LAYER_ID LayerID = wxEmptyString; ///< The sheet block is on (TODO: verify this is true)
335         LAYER_ID AssocLayerID  = wxEmptyString; ///< Parent or Child linked sheet
336         wxString Name          = wxEmptyString;
337         bool     HasBlockLabel = false;
338         ATTRIBUTE_LOCATION BlockLabel;
339 
340         std::map<TERMINAL_ID, TERMINAL> Terminals;
341         std::map<FIGURE_ID, FIGURE>     Figures;
342 
343         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
344     };
345 
346 
347     struct NET_SCH : CADSTAR_ARCHIVE_PARSER::NET
348     {
349         struct JUNCTION_SCH : CADSTAR_ARCHIVE_PARSER::NET::JUNCTION ///< "JPT" nodename.
350         {
351             TERMINALCODE_ID TerminalCodeID; ///< Usually a circle, but size can be varied
352             bool            HasNetLabel = false;
353             SIGLOC          NetLabel;
354 
355             void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
356         };
357 
358         struct SYM_TERM : PARSER ///< "TERM" nodename (represents a pin in a SCH symbol)
359         {
360             NETELEMENT_ID ID; ///< First character is "P"
361             SYMBOL_ID     SymbolID;
362             TERMINAL_ID   TerminalID;
363             bool          HasNetLabel = false;
364             SIGLOC        NetLabel;
365 
366             void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
367         };
368 
369         struct BUS_TERM : PARSER ///< "BUSTERM" nodename (represents a connection to a bus)
370         {
371             NETELEMENT_ID ID; ///< First two characters "BT"
372             BUS_ID        BusID;
373             POINT         FirstPoint;  ///< Point on the bus itself
374             POINT         SecondPoint; ///< Start point for any wires
375             bool          HasNetLabel = false;
376             SIGLOC        NetLabel;
377 
378             void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
379         };
380 
381         struct BLOCK_TERM : PARSER ///< "BLOCKTERM" nodename (represents a connection to a block)
382         {
383             NETELEMENT_ID ID; ///< First four characters "BLKT"
384             BLOCK_ID      BlockID;
385             TERMINAL_ID   TerminalID;
386             bool          HasNetLabel = false;
387             SIGLOC        NetLabel;
388 
389             void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
390         };
391 
392 
393         struct DANGLER : PARSER ///< "DANGLER" nodename (represents a dangling wire)
394         {
395             NETELEMENT_ID   ID; ///< First character "D"
396             TERMINALCODE_ID TerminalCodeID;
397             LAYER_ID        LayerID;
398             POINT           Position;
399             bool            HasNetLabel = false;
400             SIGLOC          NetLabel;
401 
402             void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
403         };
404 
405         struct CONNECTION_SCH : CADSTAR_ARCHIVE_PARSER::NET::CONNECTION ///< "CONN" nodename
406         {
407             LAYER_ID           LayerID; ///< Sheet on which the connection is drawn
408             std::vector<POINT> Path;
409             GROUP_ID           GroupID = wxEmptyString;
410             REUSEBLOCKREF      ReuseBlockRef;
411             LINECODE_ID        ConnectionLineCode;
412 
413             void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
414         };
415 
416         std::map<NETELEMENT_ID, JUNCTION_SCH> Junctions;
417         std::map<NETELEMENT_ID, SYM_TERM>     Terminals;
418         std::map<NETELEMENT_ID, BUS_TERM>     BusTerminals;
419         std::map<NETELEMENT_ID, BLOCK_TERM>   BlockTerminals;
420         std::map<NETELEMENT_ID, DANGLER>      Danglers;
421         std::vector<CONNECTION_SCH>           Connections;
422 
423         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
424     };
425 
426 
427     struct CADSTAR_SCHEMATIC : PARSER
428     {
429         std::map<GROUP_ID, GROUP>                               Groups;
430         std::map<REUSEBLOCK_ID, REUSEBLOCK>                     ReuseBlocks;
431         std::map<FIGURE_ID, FIGURE>                             Figures;
432         std::map<SYMBOL_ID, SYMBOL>                             Symbols;
433         std::map<BUS_ID, BUS>                                   Buses;
434         std::map<BLOCK_ID, BLOCK>                               Blocks;
435         std::map<NET_ID, NET_SCH>                               Nets;
436         std::map<TEXT_ID, TEXT>                                 Texts;
437         std::map<DOCUMENTATION_SYMBOL_ID, DOCUMENTATION_SYMBOL> DocumentationSymbols;
438         VARIANT_HIERARCHY                                       VariantHierarchy;
439         std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE>                 AttributeValues;
440 
441         void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override;
442     };
443 
444 
445     wxString          Filename;
446     HEADER            Header;
447     ASSIGNMENTS_SCM   Assignments;
448     LIBRARY_SCM       Library;
449     PARTS             Parts;
450     SHEETS            Sheets;
451     CADSTAR_SCHEMATIC Schematic;
452     ATTRCOLORS        AttrColors;
453     PARTNAMECOL       SymbolPartNameColor;
454 
455     int KiCadUnitDivider; ///<Use this value to convert units in this CSA file to KiCad units
456 
457 }; //CADSTAR_SCH_ARCHIVE_PARSER
458 
459 #endif // CADSTAR_SCH_ARCHIVE_PARSER_H_
460