Browse Source
ADDED: CADSTAR PCB Archive Importer
ADDED: CADSTAR PCB Archive Importer
Initial commit - Imports directly mappable layer stackup (only physical board fabrication layers for now)pull/16/head
committed by
Seth Hillbrand
19 changed files with 1394 additions and 0 deletions
-
4common/wildcards_and_files_ext.cpp
-
1cvpcb/CMakeLists.txt
-
1include/wildcards_and_files_ext.h
-
2pcbnew/CMakeLists.txt
-
14pcbnew/cadstar2kicadpcb_plugin/CMakeLists.txt
-
152pcbnew/cadstar2kicadpcb_plugin/cadstar_common.cpp
-
92pcbnew/cadstar2kicadpcb_plugin/cadstar_common.h
-
329pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb.cpp
-
54pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb.h
-
429pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_parser.cpp
-
173pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_parser.h
-
70pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_plugin.cpp
-
61pcbnew/cadstar2kicadpcb_plugin/cadstar_pcb_archive_plugin.h
-
5pcbnew/files.cpp
-
3pcbnew/io_mgr.cpp
-
1pcbnew/io_mgr.h
-
1qa/gal/gal_pixel_alignment/CMakeLists.txt
-
1qa/pcbnew/CMakeLists.txt
-
1qa/pcbnew_tools/CMakeLists.txt
@ -0,0 +1,14 @@ |
|||
|
|||
# Sources for the pcbnew PLUGIN called CADSTAR_ARCHIVE_PLUGIN |
|||
include_directories( . ) |
|||
|
|||
set( CADSTAR2PCBNEW_SRCS |
|||
cadstar_pcb_archive_plugin.cpp |
|||
cadstar_pcb_archive_parser.cpp |
|||
cadstar_common.cpp |
|||
cadstar_pcb.cpp |
|||
) |
|||
|
|||
add_library( cadstar2kicadpcb STATIC ${CADSTAR2PCBNEW_SRCS} ) |
|||
|
|||
target_link_libraries( cadstar2kicadpcb pcbcommon ) |
|||
@ -0,0 +1,152 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2020 Roberto Fernandez Bautista <@Qbort> |
|||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
/**
|
|||
* @file cadstar_common.cpp |
|||
* @brief Helper functions and common defines |
|||
*/ |
|||
|
|||
#include <cadstar_common.h>
|
|||
|
|||
XNODE* CADSTAR_COMMON::LoadArchiveFile( const wxString& aFileName, FILE_TYPE aType ) |
|||
{ |
|||
KEYWORD emptyKeywords[1] = {}; |
|||
XNODE * iNode = NULL, *cNode = NULL; |
|||
int tok; |
|||
bool cadstarFileCheckDone = false; |
|||
wxString str, fileIdentifier; |
|||
wxCSConv win1252( wxT( "windows-1252" ) ); |
|||
wxMBConv* conv = &win1252; // Initial testing suggests file encoding to be Windows-1252
|
|||
// More samples required.
|
|||
FILE* fp = wxFopen( aFileName, wxT( "rt" ) ); |
|||
|
|||
if( !fp ) |
|||
THROW_IO_ERROR( wxString::Format( _( "Cannot open file '%s'" ), aFileName ) ); |
|||
|
|||
|
|||
switch( aType ) |
|||
{ |
|||
case FILE_TYPE::PCB_ARCHIVE: |
|||
fileIdentifier = wxT( "CADSTARPCB" ); |
|||
break; |
|||
|
|||
//add others here
|
|||
// SCHEMATIC_ARCHIVE
|
|||
// ...
|
|||
|
|||
default: |
|||
wxASSERT_MSG( true, "Unknown CADSTAR filetype specified" ); |
|||
} |
|||
|
|||
DSNLEXER lexer( emptyKeywords, 0, fp, aFileName ); |
|||
|
|||
while( ( tok = lexer.NextTok() ) != DSN_EOF ) |
|||
{ |
|||
if( tok == DSN_RIGHT ) |
|||
{ |
|||
cNode = iNode; |
|||
if( cNode ) |
|||
{ |
|||
iNode = cNode->GetParent(); |
|||
} |
|||
else |
|||
{ |
|||
//too many closing brackets
|
|||
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) ); |
|||
} |
|||
} |
|||
else if( tok == DSN_LEFT ) |
|||
{ |
|||
tok = lexer.NextTok(); |
|||
str = wxString( lexer.CurText(), *conv ); |
|||
cNode = new XNODE( wxXML_ELEMENT_NODE, str ); |
|||
|
|||
if( iNode ) |
|||
{ |
|||
iNode->AddChild( cNode ); |
|||
} |
|||
else if( !cadstarFileCheckDone ) |
|||
{ |
|||
|
|||
if( cNode->GetName() != fileIdentifier ) |
|||
{ |
|||
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) ); |
|||
} |
|||
} |
|||
|
|||
iNode = cNode; |
|||
} |
|||
else if( iNode ) |
|||
{ |
|||
str = wxString( lexer.CurText(), *conv ); |
|||
|
|||
if( !str.IsEmpty() ) |
|||
{ |
|||
wxString result, paramName = "attr0"; |
|||
int i = 0; |
|||
|
|||
while( iNode->GetAttribute( paramName, &result ) ) |
|||
{ |
|||
paramName = wxT( "attr" ); |
|||
paramName << i++; |
|||
} |
|||
|
|||
iNode->AddAttribute( paramName, str ); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
//not enough closing brackets
|
|||
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) ); |
|||
} |
|||
} |
|||
|
|||
if( iNode != NULL ) |
|||
{ |
|||
//not enough closing brackets
|
|||
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) ); |
|||
} |
|||
|
|||
if( cNode ) |
|||
{ |
|||
return cNode; |
|||
} |
|||
else |
|||
{ |
|||
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) ); |
|||
} |
|||
|
|||
return NULL; |
|||
} |
|||
|
|||
wxString CADSTAR_COMMON::GetAttributeID( XNODE* aNode, unsigned int aID ) |
|||
{ |
|||
wxString attrName = "attr"; |
|||
attrName << aID; |
|||
return aNode->GetAttribute( attrName, wxEmptyString ); |
|||
} |
|||
|
|||
void CADSTAR_COMMON::CheckNoChildNodes( XNODE* aNode, wxString aLocation ) |
|||
{ |
|||
if( aNode->GetChildren() ) |
|||
{ |
|||
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aLocation ); |
|||
} |
|||
} |
|||
@ -0,0 +1,92 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2020 Roberto Fernandez Bautista <@Qbort> |
|||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
/** |
|||
* @file cadstar_common.h |
|||
* @brief Helper functions and common defines |
|||
*/ |
|||
|
|||
#ifndef CADSTAR_COMMON_H_ |
|||
#define CADSTAR_COMMON_H_ |
|||
|
|||
#include <class_board.h> |
|||
#include <dsnlexer.h> |
|||
#include <macros.h> |
|||
#include <wx/wx.h> |
|||
#include <wx/xml/xml.h> |
|||
#include <xnode.h> |
|||
|
|||
#define THROW_MISSING_NODE_IO_ERROR( nodename, location ) \ |
|||
THROW_IO_ERROR( wxString::Format( _( "Missing node '%s' in '%s'" ), nodename, location ) ) |
|||
|
|||
#define THROW_UNKNOWN_NODE_IO_ERROR( nodename, location ) \ |
|||
THROW_IO_ERROR( wxString::Format( _( "Unknown node '%s' in '%s'" ), nodename, location ) ) |
|||
|
|||
#define THROW_MISSING_PARAMETER_IO_ERROR( param, location ) \ |
|||
THROW_IO_ERROR( wxString::Format( _( "Missing Parameter '%s' in '%s'" ), param, location ) ) |
|||
|
|||
#define THROW_UNKNOWN_PARAMETER_IO_ERROR( param, location ) \ |
|||
THROW_IO_ERROR( wxString::Format( _( "Unknown Parameter '%s' in '%s'" ), param, location ) ) |
|||
|
|||
#define THROW_PARSING_IO_ERROR( param, location ) \ |
|||
THROW_IO_ERROR( wxString::Format( _( "Unable to parse '%s' in '%s'" ), param, location ) ) |
|||
|
|||
|
|||
namespace CADSTAR_COMMON |
|||
{ |
|||
enum class FILE_TYPE |
|||
{ |
|||
PCB_ARCHIVE, |
|||
SCHEMATIC_ARCHIVE //for future schematic importer |
|||
//cadstar libraries? |
|||
//etc. |
|||
}; |
|||
|
|||
|
|||
/** |
|||
* @brief Reads a CADSTAR Archive file (S-parameter format) |
|||
* @param aFileName |
|||
* @param aType |
|||
* @return XNODE pointing to the top of the tree for further parsing. Each node has the first |
|||
element as the node's name and subsequent elements as node attributes ("attr0", |
|||
"attr1", "attr2", etc.). Caller is responsible for deleting to avoid memory leaks. |
|||
* @throws IO_ERROR |
|||
*/ |
|||
extern XNODE* LoadArchiveFile( |
|||
const wxString& aFileName, FILE_TYPE aType = FILE_TYPE::PCB_ARCHIVE ); |
|||
|
|||
/** |
|||
* @brief |
|||
* @param aNode |
|||
* @param aID |
|||
* @return returns the value of attribute "attrX" in aNode where 'X' is aID |
|||
*/ |
|||
extern wxString GetAttributeID( XNODE* aNode, unsigned int aID ); |
|||
|
|||
/** |
|||
* @brief |
|||
* @param aNode |
|||
* @throw IO_ERROR if a child node was found |
|||
*/ |
|||
extern void CheckNoChildNodes( XNODE* aNode, wxString aLocation ); |
|||
|
|||
} // namespace CADSTAR_COMMON |
|||
|
|||
#endif // CADSTAR_COMMON_H_ |
|||
@ -0,0 +1,329 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2020 Roberto Fernandez Bautista <@Qbort> |
|||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
/**
|
|||
* @file cadstar_pcb.cpp |
|||
* @brief Converts a CPA_FILE object into a KiCad BOARD object |
|||
*/ |
|||
|
|||
#include <board_stackup_manager/stackup_predefined_prms.h> //KEY_COPPER, KEY_CORE, KEY_PREPREG
|
|||
#include <cadstar_pcb.h>
|
|||
|
|||
|
|||
void CADSTAR_PCB::Load( CPA_FILE* aCPAfile ) |
|||
{ |
|||
loadBoardStackup( aCPAfile ); |
|||
|
|||
//TODO: process all other items
|
|||
} |
|||
|
|||
|
|||
void CADSTAR_PCB::loadBoardStackup( CPA_FILE* aCPAfile ) |
|||
{ |
|||
std::map<CPA_LAYER_ID, CPA_LAYER>& cpaLayers = aCPAfile->Assignments.Layerdefs.Layers; |
|||
std::map<CPA_MATERIAL_ID, CPA_MATERIAL>& cpaMaterials = |
|||
aCPAfile->Assignments.Layerdefs.Materials; |
|||
std::vector<CPA_LAYER_ID>& cpaLayerStack = aCPAfile->Assignments.Layerdefs.LayerStack; |
|||
unsigned numElectricalAndPowerLayers = 0; |
|||
BOARD_DESIGN_SETTINGS& designSettings = mBoard->GetDesignSettings(); |
|||
BOARD_STACKUP& stackup = designSettings.GetStackupDescriptor(); |
|||
int noOfKiCadStackupLayers = 0; |
|||
int lastElectricalLayerIndex = 0; |
|||
int dielectricSublayer = 0; |
|||
int numDielectricLayers = 0; |
|||
bool prevWasDielectric = false; |
|||
BOARD_STACKUP_ITEM* tempKiCadLayer; |
|||
std::vector<PCB_LAYER_ID> layerIDs; |
|||
|
|||
//Remove all layers except required ones
|
|||
stackup.RemoveAll(); |
|||
layerIDs.push_back( PCB_LAYER_ID::F_CrtYd ); |
|||
layerIDs.push_back( PCB_LAYER_ID::B_CrtYd ); |
|||
layerIDs.push_back( PCB_LAYER_ID::Margin ); |
|||
layerIDs.push_back( PCB_LAYER_ID::Edge_Cuts ); |
|||
designSettings.SetEnabledLayers( LSET( &layerIDs[0], layerIDs.size() ) ); |
|||
|
|||
for( auto it = cpaLayerStack.begin(); it != cpaLayerStack.end(); ++it ) |
|||
{ |
|||
CPA_LAYER curLayer = cpaLayers[*it]; |
|||
BOARD_STACKUP_ITEM_TYPE kicadLayerType = BOARD_STACKUP_ITEM_TYPE::BS_ITEM_TYPE_UNDEFINED; |
|||
LAYER_T copperType = LAYER_T::LT_UNDEFINED; |
|||
PCB_LAYER_ID kicadLayerID = PCB_LAYER_ID::UNDEFINED_LAYER; |
|||
wxString layerTypeName = wxEmptyString; |
|||
|
|||
if( cpaLayers.count( *it ) == 0 ) |
|||
wxASSERT_MSG( true, wxT( "Unable to find layer index" ) ); |
|||
|
|||
if( prevWasDielectric && ( curLayer.Type != CPA_LAYER_TYPE::CONSTRUCTION ) ) |
|||
{ |
|||
stackup.Add( tempKiCadLayer ); //only add dielectric layers here after all are done
|
|||
dielectricSublayer = 0; |
|||
prevWasDielectric = false; |
|||
noOfKiCadStackupLayers++; |
|||
} |
|||
|
|||
switch( curLayer.Type ) |
|||
{ |
|||
case CPA_LAYER_TYPE::ALLDOC: |
|||
case CPA_LAYER_TYPE::ALLELEC: |
|||
case CPA_LAYER_TYPE::ALLLAYER: |
|||
case CPA_LAYER_TYPE::ASSCOMPCOPP: |
|||
case CPA_LAYER_TYPE::NOLAYER: |
|||
//Shouldn't be here if CPA file is correctly parsed and not corrupt
|
|||
THROW_IO_ERROR( wxString::Format( |
|||
_( "Unexpected layer '%s' in layer stack." ), curLayer.Name ) ); |
|||
continue; |
|||
case CPA_LAYER_TYPE::JUMPERLAYER: |
|||
copperType = LAYER_T::LT_JUMPER; |
|||
kicadLayerID = getKiCadCopperLayerID( numElectricalAndPowerLayers++ ); |
|||
kicadLayerType = BOARD_STACKUP_ITEM_TYPE::BS_ITEM_TYPE_COPPER; |
|||
layerTypeName = KEY_COPPER; |
|||
break; |
|||
case CPA_LAYER_TYPE::ELEC: |
|||
copperType = LAYER_T::LT_SIGNAL; |
|||
kicadLayerID = getKiCadCopperLayerID( numElectricalAndPowerLayers++ ); |
|||
kicadLayerType = BOARD_STACKUP_ITEM_TYPE::BS_ITEM_TYPE_COPPER; |
|||
layerTypeName = KEY_COPPER; |
|||
break; |
|||
case CPA_LAYER_TYPE::POWER: |
|||
copperType = LAYER_T::LT_POWER; |
|||
kicadLayerID = getKiCadCopperLayerID( numElectricalAndPowerLayers++ ); |
|||
kicadLayerType = BOARD_STACKUP_ITEM_TYPE::BS_ITEM_TYPE_COPPER; |
|||
layerTypeName = KEY_COPPER; |
|||
break; |
|||
case CPA_LAYER_TYPE::CONSTRUCTION: |
|||
kicadLayerID = PCB_LAYER_ID::UNDEFINED_LAYER; |
|||
kicadLayerType = BOARD_STACKUP_ITEM_TYPE::BS_ITEM_TYPE_DIELECTRIC; |
|||
prevWasDielectric = true; |
|||
layerTypeName = KEY_PREPREG; |
|||
//TODO handle KEY_CORE and KEY_PREPREG
|
|||
//will need to look at CADSTAR layer embedding (CPA_LAYER->Embedding)
|
|||
//check electrical layers above and below to decide if current layer is prepreg
|
|||
// or core
|
|||
break; |
|||
case CPA_LAYER_TYPE::DOC: |
|||
//TODO find out a suitable KiCad Layer alternative for this CADSTAR type
|
|||
continue; //ignore
|
|||
case CPA_LAYER_TYPE::NONELEC: |
|||
switch( curLayer.SubType ) |
|||
{ |
|||
case CPA_LAYER_SUBTYPE::LAYERSUBTYPE_ASSEMBLY: |
|||
case CPA_LAYER_SUBTYPE::LAYERSUBTYPE_NONE: |
|||
case CPA_LAYER_SUBTYPE::LAYERSUBTYPE_PLACEMENT: |
|||
//TODO find out a suitable KiCad Layer alternative for these CADSTAR types
|
|||
continue; //ignore these layer types for now
|
|||
case CPA_LAYER_SUBTYPE::LAYERSUBTYPE_PASTE: |
|||
kicadLayerType = BOARD_STACKUP_ITEM_TYPE::BS_ITEM_TYPE_SOLDERPASTE; |
|||
if( numElectricalAndPowerLayers > 0 ) |
|||
{ |
|||
kicadLayerID = PCB_LAYER_ID::F_Paste; |
|||
layerTypeName = _HKI( "Top Solder Paste" ); |
|||
} |
|||
else |
|||
{ |
|||
kicadLayerID = PCB_LAYER_ID::B_Paste; |
|||
layerTypeName = _HKI( "Bottom Solder Paste" ); |
|||
} |
|||
break; |
|||
case CPA_LAYER_SUBTYPE::LAYERSUBTYPE_SILKSCREEN: |
|||
kicadLayerType = BOARD_STACKUP_ITEM_TYPE::BS_ITEM_TYPE_SILKSCREEN; |
|||
if( numElectricalAndPowerLayers > 0 ) |
|||
{ |
|||
kicadLayerID = PCB_LAYER_ID::F_SilkS; |
|||
layerTypeName = _HKI( "Top Silk Screen" ); |
|||
} |
|||
else |
|||
{ |
|||
kicadLayerID = PCB_LAYER_ID::B_SilkS; |
|||
layerTypeName = _HKI( "Bottom Silk Screen" ); |
|||
} |
|||
break; |
|||
case CPA_LAYER_SUBTYPE::LAYERSUBTYPE_SOLDERRESIST: |
|||
kicadLayerType = BOARD_STACKUP_ITEM_TYPE::BS_ITEM_TYPE_SOLDERMASK; |
|||
if( numElectricalAndPowerLayers > 0 ) |
|||
{ |
|||
kicadLayerID = PCB_LAYER_ID::F_Mask; |
|||
layerTypeName = _HKI( "Top Solder Mask" ); |
|||
} |
|||
else |
|||
{ |
|||
kicadLayerID = PCB_LAYER_ID::B_Mask; |
|||
layerTypeName = _HKI( "Bottom Solder Mask" ); |
|||
} |
|||
break; |
|||
default: |
|||
wxASSERT_MSG( true, wxT( "Unknown CADSTAR Layer Sub-type" ) ); |
|||
break; |
|||
} |
|||
break; |
|||
default: |
|||
wxASSERT_MSG( true, wxT( "Unknown CADSTAR Layer Type" ) ); |
|||
break; |
|||
} |
|||
|
|||
if( dielectricSublayer == 0 ) |
|||
tempKiCadLayer = new BOARD_STACKUP_ITEM( kicadLayerType ); |
|||
|
|||
tempKiCadLayer->SetLayerName( curLayer.Name ); |
|||
tempKiCadLayer->SetBrdLayerId( kicadLayerID ); |
|||
|
|||
if( prevWasDielectric ) |
|||
{ |
|||
wxASSERT_MSG( kicadLayerID == PCB_LAYER_ID::UNDEFINED_LAYER, |
|||
wxT( "Error Processing Dielectric Layer. " |
|||
"Expected to have undefined layer type" ) ); |
|||
|
|||
if( dielectricSublayer == 0 ) |
|||
tempKiCadLayer->SetDielectricLayerId( ++numDielectricLayers ); |
|||
else |
|||
tempKiCadLayer->AddDielectricPrms( dielectricSublayer ); |
|||
} |
|||
|
|||
if( !curLayer.MaterialId.IsEmpty() ) |
|||
{ |
|||
tempKiCadLayer->SetMaterial( |
|||
cpaMaterials[curLayer.MaterialId].Name, dielectricSublayer ); |
|||
tempKiCadLayer->SetEpsilonR( cpaMaterials[curLayer.MaterialId].Permittivity.GetDouble(), |
|||
dielectricSublayer ); |
|||
tempKiCadLayer->SetLossTangent( |
|||
cpaMaterials[curLayer.MaterialId].LossTangent.GetDouble(), dielectricSublayer ); |
|||
//TODO add Resistivity when KiCad supports it
|
|||
} |
|||
|
|||
int unitMultiplier = 10; //assume CPA_FILE uses HUNDREDTH MICRON as its unit
|
|||
//TODO: read units from CPA_FILE header and change unitMultiplier
|
|||
// Also, add unitMultiplier somewhere in CPA_FILE
|
|||
tempKiCadLayer->SetThickness( curLayer.Thickness * unitMultiplier, dielectricSublayer ); |
|||
|
|||
wxASSERT( layerTypeName != wxEmptyString ); |
|||
tempKiCadLayer->SetTypeName( layerTypeName ); |
|||
|
|||
if( !prevWasDielectric ) |
|||
{ |
|||
stackup.Add( tempKiCadLayer ); //only add non-dielectric layers here
|
|||
++noOfKiCadStackupLayers; |
|||
layerIDs.push_back( tempKiCadLayer->GetBrdLayerId() ); |
|||
designSettings.SetEnabledLayers( LSET( &layerIDs[0], layerIDs.size() ) ); |
|||
} |
|||
else |
|||
++dielectricSublayer; |
|||
|
|||
if( copperType != LAYER_T::LT_UNDEFINED ) |
|||
{ |
|||
wxASSERT( mBoard->SetLayerType( tempKiCadLayer->GetBrdLayerId(), |
|||
copperType ) ); //move to outside, need to enable layer in board first
|
|||
lastElectricalLayerIndex = noOfKiCadStackupLayers - 1; |
|||
wxASSERT( mBoard->SetLayerName( |
|||
tempKiCadLayer->GetBrdLayerId(), tempKiCadLayer->GetLayerName() ) ); |
|||
//TODO set layer names for other CADSTAR layers when KiCad supports custom
|
|||
//layer names on non-copper layers
|
|||
} |
|||
//TODO map kicad layer to CADSTAR layer in mLayermap
|
|||
} |
|||
|
|||
//change last copper layer to be B_Cu instead of an inner layer
|
|||
PCB_LAYER_ID lastElecBrdId = |
|||
stackup.GetStackupLayer( lastElectricalLayerIndex )->GetBrdLayerId(); |
|||
std::remove( layerIDs.begin(), layerIDs.end(), lastElecBrdId ); |
|||
layerIDs.push_back( PCB_LAYER_ID::B_Cu ); |
|||
tempKiCadLayer = stackup.GetStackupLayer( lastElectricalLayerIndex ); |
|||
tempKiCadLayer->SetBrdLayerId( PCB_LAYER_ID::B_Cu ); |
|||
wxASSERT( mBoard->SetLayerName( |
|||
tempKiCadLayer->GetBrdLayerId(), tempKiCadLayer->GetLayerName() ) ); |
|||
|
|||
//make all layers enabled and visible
|
|||
mBoard->SetEnabledLayers( LSET( &layerIDs[0], layerIDs.size() ) ); |
|||
mBoard->SetVisibleLayers( LSET( &layerIDs[0], layerIDs.size() ) ); |
|||
|
|||
mBoard->SetCopperLayerCount( numElectricalAndPowerLayers ); |
|||
} |
|||
|
|||
|
|||
PCB_LAYER_ID CADSTAR_PCB::getKiCadCopperLayerID( unsigned int aLayerNum ) |
|||
{ |
|||
switch( aLayerNum ) |
|||
{ |
|||
case 0: |
|||
return PCB_LAYER_ID::F_Cu; |
|||
case 1: |
|||
return PCB_LAYER_ID::In1_Cu; |
|||
case 2: |
|||
return PCB_LAYER_ID::In2_Cu; |
|||
case 3: |
|||
return PCB_LAYER_ID::In3_Cu; |
|||
case 4: |
|||
return PCB_LAYER_ID::In4_Cu; |
|||
case 5: |
|||
return PCB_LAYER_ID::In5_Cu; |
|||
case 6: |
|||
return PCB_LAYER_ID::In6_Cu; |
|||
case 7: |
|||
return PCB_LAYER_ID::In7_Cu; |
|||
case 8: |
|||
return PCB_LAYER_ID::In8_Cu; |
|||
case 9: |
|||
return PCB_LAYER_ID::In9_Cu; |
|||
case 10: |
|||
return PCB_LAYER_ID::In10_Cu; |
|||
case 11: |
|||
return PCB_LAYER_ID::In11_Cu; |
|||
case 12: |
|||
return PCB_LAYER_ID::In12_Cu; |
|||
case 13: |
|||
return PCB_LAYER_ID::In13_Cu; |
|||
case 14: |
|||
return PCB_LAYER_ID::In14_Cu; |
|||
case 15: |
|||
return PCB_LAYER_ID::In15_Cu; |
|||
case 16: |
|||
return PCB_LAYER_ID::In16_Cu; |
|||
case 17: |
|||
return PCB_LAYER_ID::In17_Cu; |
|||
case 18: |
|||
return PCB_LAYER_ID::In18_Cu; |
|||
case 19: |
|||
return PCB_LAYER_ID::In19_Cu; |
|||
case 20: |
|||
return PCB_LAYER_ID::In20_Cu; |
|||
case 21: |
|||
return PCB_LAYER_ID::In21_Cu; |
|||
case 22: |
|||
return PCB_LAYER_ID::In22_Cu; |
|||
case 23: |
|||
return PCB_LAYER_ID::In23_Cu; |
|||
case 24: |
|||
return PCB_LAYER_ID::In24_Cu; |
|||
case 25: |
|||
return PCB_LAYER_ID::In25_Cu; |
|||
case 26: |
|||
return PCB_LAYER_ID::In26_Cu; |
|||
case 27: |
|||
return PCB_LAYER_ID::In27_Cu; |
|||
case 28: |
|||
return PCB_LAYER_ID::In28_Cu; |
|||
case 29: |
|||
return PCB_LAYER_ID::In29_Cu; |
|||
case 30: |
|||
return PCB_LAYER_ID::In30_Cu; |
|||
case 31: |
|||
return PCB_LAYER_ID::B_Cu; |
|||
} |
|||
return PCB_LAYER_ID::UNDEFINED_LAYER; |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2020 Roberto Fernandez Bautista <@Qbort> |
|||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
/** |
|||
* @file cadstar_pcb.h |
|||
* @brief Converts a CPA_FILE object into a KiCad BOARD object |
|||
*/ |
|||
|
|||
#ifndef CADSTAR_PCB_H_ |
|||
#define CADSTAR_PCB_H_ |
|||
|
|||
#include <cadstar_pcb_archive_parser.h> |
|||
|
|||
class BOARD; |
|||
|
|||
class CADSTAR_PCB |
|||
{ |
|||
public: |
|||
explicit CADSTAR_PCB( BOARD* aBoard ) : mBoard( aBoard ) |
|||
{ |
|||
} |
|||
|
|||
/** |
|||
* @brief Loads a CADSTAR PCB Archive into the KiCad BOARD |
|||
* @param aCPAfile |
|||
*/ |
|||
void Load( CPA_FILE* aCPAfile ); |
|||
|
|||
private: |
|||
BOARD* mBoard; |
|||
std::map<CPA_LAYER_ID, PCB_LAYER_ID> mLayermap; |
|||
void loadBoardStackup( CPA_FILE* aCPAfile ); |
|||
PCB_LAYER_ID getKiCadCopperLayerID( unsigned int aLayerNum ); |
|||
}; |
|||
|
|||
|
|||
#endif // CADSTAR_PCB_H_ |
|||
@ -0,0 +1,429 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2020 Roberto Fernandez Bautista <@Qbort> |
|||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
/**
|
|||
* @file cadstar_pcb_archive_parser.cpp |
|||
* @brief Parses a CADSTAR PCB Archive file |
|||
*/ |
|||
|
|||
#include <cadstar_pcb_archive_parser.h>
|
|||
#include <cmath> // pow()
|
|||
|
|||
|
|||
void CPA_FILE::Parse() |
|||
{ |
|||
XNODE* fileRootNode = |
|||
CADSTAR_COMMON::LoadArchiveFile( Filename, CADSTAR_COMMON::FILE_TYPE::PCB_ARCHIVE ); |
|||
|
|||
XNODE* tempNode = fileRootNode->GetChildren(); |
|||
|
|||
for( ; tempNode && ( tempNode->GetName() != wxT( "ASSIGNMENTS" ) ); |
|||
tempNode = tempNode->GetNext() ) |
|||
; |
|||
|
|||
if( !tempNode ) |
|||
THROW_MISSING_NODE_IO_ERROR( wxT( "ASSIGNMENTS" ), wxT( "CADSTARPCB" ) ); |
|||
|
|||
tempNode = tempNode->GetChildren(); |
|||
|
|||
for( ; tempNode && ( tempNode->GetName() != wxT( "LAYERDEFS" ) ); |
|||
tempNode = tempNode->GetNext() ) |
|||
; |
|||
|
|||
if( !tempNode ) |
|||
THROW_MISSING_NODE_IO_ERROR( wxT( "LAYERDEFS" ), wxT( "ASSIGNMENTS" ) ); |
|||
|
|||
Assignments.Layerdefs.Parse( tempNode ); |
|||
|
|||
//Todo - This is just for testing. Remove this block & delete fileRootNode.
|
|||
{ |
|||
wxXmlDocument doc; |
|||
doc.SetRoot( fileRootNode ); |
|||
doc.Save( Filename + wxT( ".xml" ) ); |
|||
} |
|||
|
|||
//delete fileRootNode;
|
|||
|
|||
//TODO need to parse everything else!
|
|||
} |
|||
|
|||
void CPA_LAYERDEFS::Parse( XNODE* aNode ) |
|||
{ |
|||
wxASSERT( aNode->GetName() == wxT( "LAYERDEFS" ) ); |
|||
XNODE * iNode, *cNode; |
|||
wxXmlAttribute* xmlAttribute = NULL; |
|||
|
|||
iNode = aNode->GetChildren(); |
|||
|
|||
if( !iNode ) |
|||
THROW_MISSING_PARAMETER_IO_ERROR( wxT( "LAYERSTACK" ), wxT( "LAYERDEFS" ) ); |
|||
|
|||
for( ; iNode; iNode = iNode->GetNext() ) |
|||
{ |
|||
wxString nodeName = iNode->GetName(); |
|||
|
|||
if( nodeName == wxT( "LAYERSTACK" ) ) |
|||
{ |
|||
xmlAttribute = iNode->GetAttributes(); |
|||
|
|||
for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() ) |
|||
{ |
|||
LayerStack.push_back( xmlAttribute->GetValue() ); |
|||
} |
|||
|
|||
if( cNode = iNode->GetChildren() ) //Shouldn't have any children
|
|||
{ |
|||
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), nodeName ); |
|||
} |
|||
} |
|||
else if( nodeName == wxT( "MATERIAL" ) ) |
|||
{ |
|||
CPA_MATERIAL material; |
|||
material.Parse( iNode ); |
|||
Materials.insert( std::make_pair( material.ID, material ) ); |
|||
} |
|||
else if( nodeName == wxT( "LAYER" ) ) |
|||
{ |
|||
CPA_LAYER layer; |
|||
layer.Parse( iNode ); |
|||
Layers.insert( std::make_pair( layer.ID, layer ) ); |
|||
} |
|||
else if( nodeName == wxT( "SWAPPAIR" ) ) |
|||
{ |
|||
wxString layerId = CADSTAR_COMMON::GetAttributeID( iNode, 0 ); |
|||
wxString swapLayerId = CADSTAR_COMMON::GetAttributeID( iNode, 1 ); |
|||
|
|||
if( layerId.IsEmpty() || swapLayerId.IsEmpty() ) |
|||
{ |
|||
THROW_MISSING_PARAMETER_IO_ERROR( |
|||
wxT( "ID" ), wxString::Format( "SWAPPAIR %s,%s", layerId, swapLayerId ) ); |
|||
} |
|||
|
|||
Layers[layerId].SwapLayerID = swapLayerId; |
|||
} |
|||
else |
|||
{ |
|||
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, aNode->GetName() ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
void CPAParseEValue( XNODE* aNode, CPA_EVALUE& aValue, wxString location ) |
|||
{ |
|||
if( aNode->GetChildren()->GetName() == wxT( "E" ) ) |
|||
{ |
|||
aValue.Parse( aNode->GetChildren() ); |
|||
} |
|||
else |
|||
{ |
|||
THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), location ); |
|||
} |
|||
} |
|||
|
|||
|
|||
void CPAParseNameAndID( XNODE* aNode, wxString& aName, wxString& aID ) |
|||
{ |
|||
aID = CADSTAR_COMMON::GetAttributeID( aNode, 0 ); |
|||
aName = CADSTAR_COMMON::GetAttributeID( aNode, 1 ); |
|||
|
|||
if( aID.IsEmpty() ) |
|||
THROW_MISSING_PARAMETER_IO_ERROR( |
|||
wxT( "ID" ), wxString::Format( "%s %s", aNode->GetName(), aName ) ); |
|||
|
|||
if( aName.IsEmpty() ) |
|||
THROW_MISSING_PARAMETER_IO_ERROR( |
|||
wxT( "Name" ), wxString::Format( "%s %s", aNode->GetName(), aID ) ); |
|||
} |
|||
|
|||
void CPA_MATERIAL::Parse( XNODE* aNode ) |
|||
{ |
|||
wxASSERT( aNode->GetName() == wxT( "MATERIAL" ) ); |
|||
|
|||
//Process Name & ID
|
|||
CPAParseNameAndID( aNode, Name, ID ); |
|||
|
|||
//Process Type
|
|||
wxString sType = CADSTAR_COMMON::GetAttributeID( aNode, 2 ); |
|||
|
|||
if( sType == wxT( "CONSTRUCTION" ) ) |
|||
{ |
|||
Type = CPA_MATERIAL_LAYER_TYPE::CONSTRUCTION; |
|||
} |
|||
else if( sType == wxT( "ELECTRICAL" ) ) |
|||
{ |
|||
Type = CPA_MATERIAL_LAYER_TYPE::ELECTRICAL; |
|||
} |
|||
else if( sType == wxT( "NONELEC" ) ) |
|||
{ |
|||
Type = CPA_MATERIAL_LAYER_TYPE::NON_ELECTRICAL; |
|||
} |
|||
else |
|||
{ |
|||
THROW_UNKNOWN_PARAMETER_IO_ERROR( sType, wxString::Format( "MATERIAL %s", Name ) ); |
|||
} |
|||
|
|||
//Process electrical values
|
|||
XNODE* iNode = aNode->GetChildren(); |
|||
|
|||
if( !iNode ) |
|||
THROW_MISSING_PARAMETER_IO_ERROR( |
|||
wxT( "RESISTIVITY" ), wxString::Format( "MATERIAL %s", Name ) ); |
|||
|
|||
for( ; iNode; iNode = iNode->GetNext() ) |
|||
{ |
|||
wxString nodeName = iNode->GetName(); |
|||
wxString location = wxString::Format( "MATERIAL %s->%s", Name, nodeName ); |
|||
|
|||
if( nodeName == wxT( "RELPERMIT" ) ) |
|||
{ |
|||
CPAParseEValue( iNode, Permittivity, location ); |
|||
} |
|||
else if( nodeName == wxT( "LOSSTANGENT" ) ) |
|||
{ |
|||
CPAParseEValue( iNode, LossTangent, location ); |
|||
} |
|||
else if( nodeName == wxT( "RESISTIVITY" ) ) |
|||
{ |
|||
CPAParseEValue( iNode, Resistivity, location ); |
|||
} |
|||
else |
|||
{ |
|||
THROW_UNKNOWN_NODE_IO_ERROR( nodeName, wxString::Format( "MATERIAL %s", Name ) ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void CPA_LAYER::Parse( XNODE* aNode ) |
|||
{ |
|||
wxASSERT( aNode->GetName() == wxT( "LAYER" ) ); |
|||
|
|||
//Process Name & ID
|
|||
CPAParseNameAndID( aNode, Name, ID ); |
|||
|
|||
XNODE* cNode = aNode->GetChildren(); |
|||
auto processLayerMaterialDetails = [&]() { |
|||
XNODE* tempNode = cNode->GetChildren(); |
|||
for( ; tempNode; tempNode = tempNode->GetNext() ) |
|||
{ |
|||
wxString tempNodeName = tempNode->GetName(); |
|||
|
|||
if( tempNodeName == wxT( "MAKE" ) ) |
|||
{ |
|||
//Process material ID and layer width
|
|||
MaterialId = CADSTAR_COMMON::GetAttributeID( tempNode, 0 ); |
|||
|
|||
if( MaterialId.IsEmpty() ) |
|||
THROW_PARSING_IO_ERROR( |
|||
wxT( "Material ID" ), wxString::Format( "LAYER %s->MAKE", Name ) ); |
|||
|
|||
if( !CADSTAR_COMMON::GetAttributeID( tempNode, 1 ).ToLong( &Thickness ) ) |
|||
THROW_PARSING_IO_ERROR( |
|||
wxT( "Thickness" ), wxString::Format( "LAYER %s->MAKE", Name ) ); |
|||
|
|||
XNODE* childOfTempNode = tempNode->GetChildren(); |
|||
|
|||
if( childOfTempNode ) |
|||
{ |
|||
if( childOfTempNode->GetName() == wxT( "EMBEDS" ) ) |
|||
{ |
|||
// if( UPWARDS
|
|||
wxString embedsValue = CADSTAR_COMMON::GetAttributeID( childOfTempNode, 0 ); |
|||
|
|||
if( embedsValue == wxT( "UPWARDS" ) ) |
|||
{ |
|||
Embedding = CPA_EMBEDDING::ABOVE; |
|||
} |
|||
else if( embedsValue == wxT( "DOWNWARDS" ) ) |
|||
{ |
|||
Embedding = CPA_EMBEDDING::BELOW; |
|||
} |
|||
else |
|||
{ |
|||
THROW_UNKNOWN_PARAMETER_IO_ERROR( |
|||
embedsValue, wxString::Format( "LAYER %s -> EMBEDS", Name ) ); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
THROW_UNKNOWN_NODE_IO_ERROR( childOfTempNode->GetName(), |
|||
wxString::Format( "LAYER %s->MAKE", Name ) ); |
|||
} |
|||
} |
|||
} |
|||
else if( tempNodeName == wxT( "BIAS" ) ) |
|||
{ |
|||
wxString bias = CADSTAR_COMMON::GetAttributeID( tempNode, 0 ); |
|||
|
|||
if( bias == wxT( "X_BIASED" ) ) |
|||
{ |
|||
RoutingBias = CPA_ROUTING_BIAS::X; |
|||
} |
|||
else if( bias == wxT( "Y_BIASED" ) ) |
|||
{ |
|||
RoutingBias = CPA_ROUTING_BIAS::Y; |
|||
} |
|||
else if( bias == wxT( "ANTITRACK" ) ) |
|||
{ |
|||
RoutingBias = CPA_ROUTING_BIAS::ANTI_ROUTE; |
|||
} |
|||
else if( bias == wxT( "OBSTACLE" ) ) |
|||
{ |
|||
RoutingBias = CPA_ROUTING_BIAS::OBSTACLE; |
|||
} |
|||
else if( bias == wxT( "UNBIASED" ) ) |
|||
{ |
|||
RoutingBias = CPA_ROUTING_BIAS::UNBIASED; |
|||
} |
|||
else |
|||
{ |
|||
THROW_UNKNOWN_PARAMETER_IO_ERROR( |
|||
bias, wxString::Format( "LAYER %s -> BIAS", Name ) ); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
THROW_UNKNOWN_NODE_IO_ERROR( tempNodeName, wxString::Format( "LAYER %s", Name ) ); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
for( ; cNode; cNode = cNode->GetNext() ) |
|||
{ |
|||
//TODO ADD CHECK TO MAKE SURE THERE ARE NO CHILD NODES
|
|||
|
|||
wxString cNodeName = cNode->GetName(); |
|||
|
|||
if( cNodeName == wxT( "ALLDOC" ) ) |
|||
{ |
|||
Type = CPA_LAYER_TYPE::ALLDOC; |
|||
} |
|||
else if( cNodeName == wxT( "ALLELEC" ) ) |
|||
{ |
|||
Type = CPA_LAYER_TYPE::ALLELEC; |
|||
} |
|||
else if( cNodeName == wxT( "ALLLAYER" ) ) |
|||
{ |
|||
Type = CPA_LAYER_TYPE::ALLLAYER; |
|||
} |
|||
else if( cNodeName == wxT( "ASSCOMPCOPP" ) ) |
|||
{ |
|||
Type = CPA_LAYER_TYPE::ASSCOMPCOPP; |
|||
} |
|||
else if( cNodeName == wxT( "JUMPERLAYER" ) ) |
|||
{ |
|||
Type = CPA_LAYER_TYPE::JUMPERLAYER; |
|||
} |
|||
else if( cNodeName == wxT( "NOLAYER" ) ) |
|||
{ |
|||
Type = CPA_LAYER_TYPE::NOLAYER; |
|||
} |
|||
else if( cNodeName == wxT( "POWER" ) ) |
|||
{ |
|||
Type = CPA_LAYER_TYPE::POWER; |
|||
|
|||
if( !CADSTAR_COMMON::GetAttributeID( cNode, 0 ).ToLong( &PhysicalLayer ) ) |
|||
THROW_PARSING_IO_ERROR( |
|||
wxT( "Physical Layer" ), wxString::Format( "LAYER %s", Name ) ); |
|||
|
|||
processLayerMaterialDetails(); |
|||
} |
|||
else if( cNodeName == wxT( "DOC" ) ) |
|||
{ |
|||
Type = CPA_LAYER_TYPE::DOC; |
|||
} |
|||
else if( cNodeName == wxT( "CONSTRUCTION" ) ) |
|||
{ |
|||
Type = CPA_LAYER_TYPE::CONSTRUCTION; |
|||
processLayerMaterialDetails(); |
|||
} |
|||
else if( cNodeName == wxT( "ELEC" ) ) |
|||
{ |
|||
Type = CPA_LAYER_TYPE::ELEC; |
|||
|
|||
if( !CADSTAR_COMMON::GetAttributeID( cNode, 0 ).ToLong( &PhysicalLayer ) ) |
|||
THROW_PARSING_IO_ERROR( |
|||
wxT( "Physical Layer" ), wxString::Format( "LAYER %s", Name ) ); |
|||
|
|||
processLayerMaterialDetails(); |
|||
} |
|||
else if( cNodeName == wxT( "NONELEC" ) ) |
|||
{ |
|||
Type = CPA_LAYER_TYPE::NONELEC; |
|||
|
|||
if( !CADSTAR_COMMON::GetAttributeID( cNode, 0 ).ToLong( &PhysicalLayer ) ) |
|||
THROW_PARSING_IO_ERROR( |
|||
wxT( "Physical Layer" ), wxString::Format( "LAYER %s", Name ) ); |
|||
|
|||
processLayerMaterialDetails(); |
|||
} |
|||
else if( cNodeName == wxT( "LASUBTYP" ) ) |
|||
{ |
|||
//Process subtype
|
|||
wxString sSubType = CADSTAR_COMMON::GetAttributeID( cNode, 0 ); |
|||
|
|||
if( sSubType == wxT( "LAYERSUBTYPE_ASSEMBLY" ) ) |
|||
{ |
|||
this->SubType = CPA_LAYER_SUBTYPE::LAYERSUBTYPE_ASSEMBLY; |
|||
} |
|||
else if( sSubType == wxT( "LAYERSUBTYPE_PASTE" ) ) |
|||
{ |
|||
this->SubType = CPA_LAYER_SUBTYPE::LAYERSUBTYPE_PASTE; |
|||
} |
|||
else if( sSubType == wxT( "LAYERSUBTYPE_PLACEMENT" ) ) |
|||
{ |
|||
this->SubType = CPA_LAYER_SUBTYPE::LAYERSUBTYPE_PLACEMENT; |
|||
} |
|||
else if( sSubType == wxT( "LAYERSUBTYPE_SILKSCREEN" ) ) |
|||
{ |
|||
this->SubType = CPA_LAYER_SUBTYPE::LAYERSUBTYPE_SILKSCREEN; |
|||
} |
|||
else if( sSubType == wxT( "LAYERSUBTYPE_SOLDERRESIST" ) ) |
|||
{ |
|||
this->SubType = CPA_LAYER_SUBTYPE::LAYERSUBTYPE_SOLDERRESIST; |
|||
} |
|||
else |
|||
{ |
|||
THROW_UNKNOWN_PARAMETER_IO_ERROR( |
|||
sSubType, wxString::Format( "LAYER %s %s", Name, cNodeName ) ); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxString::Format( "LAYER %s", Name ) ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void CPA_EVALUE::Parse( XNODE* aNode ) |
|||
{ |
|||
wxASSERT( aNode->GetName() == wxT( "E" ) ); |
|||
|
|||
if( ( !CADSTAR_COMMON::GetAttributeID( aNode, 0 ).ToLong( &Base ) ) |
|||
|| ( !CADSTAR_COMMON::GetAttributeID( aNode, 1 ).ToLong( &Exponent ) ) ) |
|||
THROW_PARSING_IO_ERROR( wxT( "Base and Exponent" ), |
|||
wxString::Format( |
|||
"%s->%s", aNode->GetParent()->GetName(), aNode->GetParent()->GetName() ) ); |
|||
} |
|||
|
|||
double CPA_EVALUE::GetDouble() |
|||
{ |
|||
return Base * std::pow( 10.0, Exponent ); |
|||
} |
|||
@ -0,0 +1,173 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2020 Roberto Fernandez Bautista <@Qbort> |
|||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
/** |
|||
* @file cadstar_pcb_archive_parser.cpp |
|||
* @brief Reads in a CADSTAR PCB Archive (*.cpa) file |
|||
*/ |
|||
|
|||
#ifndef CADSTAR_PCB_ARCHIVE_PARSER_H_ |
|||
#define CADSTAR_PCB_ARCHIVE_PARSER_H_ |
|||
|
|||
#include <cadstar_common.h> |
|||
#include <map> |
|||
|
|||
/** |
|||
* @brief Represents a floating value in E notation |
|||
*/ |
|||
struct CPA_EVALUE |
|||
{ |
|||
long Base = 0; |
|||
long Exponent = 0; |
|||
|
|||
void Parse( XNODE* aNode ); |
|||
double GetDouble(); |
|||
}; |
|||
|
|||
|
|||
typedef wxString CPA_MATERIAL_ID; |
|||
|
|||
typedef wxString CPA_LAYER_ID; |
|||
|
|||
/** |
|||
* @brief subset of CPA_LAYER_TYPE - for materials only |
|||
*/ |
|||
enum class CPA_MATERIAL_LAYER_TYPE |
|||
{ |
|||
CONSTRUCTION, |
|||
ELECTRICAL, |
|||
NON_ELECTRICAL |
|||
}; |
|||
|
|||
struct CPA_MATERIAL |
|||
{ |
|||
CPA_MATERIAL_ID ID; |
|||
wxString Name; |
|||
CPA_MATERIAL_LAYER_TYPE Type; //<Type of layer appropriate for the material being set up |
|||
CPA_EVALUE Permittivity; |
|||
CPA_EVALUE LossTangent; |
|||
CPA_EVALUE Resistivity; //< x10^-8 ohm*metre |
|||
|
|||
void Parse( XNODE* aNode ); |
|||
}; |
|||
|
|||
enum class CPA_LAYER_TYPE |
|||
{ |
|||
UNDEFINED, //< Only used for error detection |
|||
ALLLAYER, //< Inbuilt layer type (cannot be assigned to user layers) |
|||
ALLELEC, //< Inbuilt layer type (cannot be assigned to user layers) |
|||
ALLDOC, //< Inbuilt layer type (cannot be assigned to user layers) |
|||
NOLAYER, //< Inbuilt layer type (cannot be assigned to user layers) |
|||
ASSCOMPCOPP, //< Inbuilt layer type (cannot be assigned to user layers) |
|||
JUMPERLAYER, //< Inbuilt layer type (cannot be assigned to user layers) |
|||
ELEC, |
|||
POWER, |
|||
NONELEC, //< This type has subtypes |
|||
CONSTRUCTION, |
|||
DOC |
|||
}; |
|||
|
|||
enum class CPA_LAYER_SUBTYPE |
|||
{ |
|||
LAYERSUBTYPE_NONE, |
|||
LAYERSUBTYPE_SILKSCREEN, |
|||
LAYERSUBTYPE_PLACEMENT, |
|||
LAYERSUBTYPE_ASSEMBLY, |
|||
LAYERSUBTYPE_SOLDERRESIST, |
|||
LAYERSUBTYPE_PASTE |
|||
}; |
|||
|
|||
enum class CPA_ROUTING_BIAS |
|||
{ |
|||
UNBIASED, //<Keyword "UNBIASED" (default) |
|||
X, //<Keyword "X_BIASED" |
|||
Y, //<Keyword "Y_BIASED" |
|||
ANTI_ROUTE, //<Keyword "ANTITRACK" |
|||
OBSTACLE //<Keyword "OBSTACLE" |
|||
}; |
|||
|
|||
enum class CPA_EMBEDDING |
|||
{ |
|||
NONE, |
|||
ABOVE, |
|||
BELOW |
|||
}; |
|||
|
|||
struct CPA_LAYER |
|||
{ |
|||
CPA_LAYER_ID ID; |
|||
wxString Name; |
|||
CPA_LAYER_TYPE Type = CPA_LAYER_TYPE::UNDEFINED; |
|||
CPA_LAYER_SUBTYPE SubType = CPA_LAYER_SUBTYPE::LAYERSUBTYPE_NONE; |
|||
long PhysicalLayer = 0; //< If 0, no physical layer is assigned |
|||
// (e.g. documentation and construction layers) |
|||
CPA_LAYER_ID SwapLayerID = wxEmptyString; //< If empty, no swap layer |
|||
CPA_ROUTING_BIAS RoutingBias = CPA_ROUTING_BIAS::UNBIASED; |
|||
long Thickness = 0; //< Note: Units of length are defined in file header |
|||
CPA_MATERIAL_ID MaterialId; |
|||
CPA_EMBEDDING Embedding = CPA_EMBEDDING::NONE; |
|||
|
|||
void Parse( XNODE* aNode ); |
|||
}; |
|||
|
|||
struct CPA_LAYERDEFS |
|||
{ |
|||
std::map<CPA_MATERIAL_ID, CPA_MATERIAL> Materials; |
|||
std::map<CPA_LAYER_ID, CPA_LAYER> Layers; |
|||
std::vector<CPA_LAYER_ID> LayerStack; |
|||
|
|||
void Parse( XNODE* aNode ); |
|||
}; |
|||
|
|||
struct CPA_ASSIGNMENTS |
|||
{ |
|||
CPA_LAYERDEFS Layerdefs; |
|||
//Todo Add codedefs, technology, grids, etc. |
|||
}; |
|||
|
|||
/** |
|||
* @brief Represents a CADSTAR PCB Archive (CPA) file |
|||
*/ |
|||
class CPA_FILE |
|||
{ |
|||
public: |
|||
explicit CPA_FILE( wxString aFilename ) : Filename( aFilename ) |
|||
{ |
|||
} |
|||
|
|||
/** |
|||
* @brief Parses the file |
|||
* @throw IO_ERROR if file could not be opened or there was |
|||
* an error while parsing |
|||
*/ |
|||
void Parse(); |
|||
|
|||
wxString Filename; |
|||
|
|||
CPA_ASSIGNMENTS Assignments; |
|||
//Todo Add Header, Library, Defaults, etc.. |
|||
}; |
|||
|
|||
//Helper Functions |
|||
void CPAParseEValue( XNODE* aNode, CPA_EVALUE& aValue, wxString location ); |
|||
void CPAParseNameAndID( XNODE* aNode, wxString& aName, wxString& aID ); |
|||
|
|||
|
|||
#endif // CADSTAR_PCB_ARCHIVE_PARSER_H_ |
|||
@ -0,0 +1,70 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2020 Roberto Fernandez Bautista <@Qbort> |
|||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
/**
|
|||
* @file cadstar_pcb_archive_plugin.cpp |
|||
* @brief Pcbnew PLUGIN for CADSTAR PCB Archive (*.cpa) format: an ASCII format |
|||
* based on S-expressions. |
|||
*/ |
|||
|
|||
#include <cadstar_common.h>
|
|||
#include <cadstar_pcb.h>
|
|||
#include <cadstar_pcb_archive_parser.h>
|
|||
#include <cadstar_pcb_archive_plugin.h>
|
|||
#include <class_board.h>
|
|||
|
|||
|
|||
CADSTAR_PCB_ARCHIVE_PLUGIN::CADSTAR_PCB_ARCHIVE_PLUGIN() |
|||
{ |
|||
m_board = nullptr; |
|||
m_props = nullptr; |
|||
} |
|||
|
|||
|
|||
CADSTAR_PCB_ARCHIVE_PLUGIN::~CADSTAR_PCB_ARCHIVE_PLUGIN() |
|||
{ |
|||
} |
|||
|
|||
|
|||
const wxString CADSTAR_PCB_ARCHIVE_PLUGIN::PluginName() const |
|||
{ |
|||
return wxT( "CADSTAR PCB Archive" ); |
|||
} |
|||
|
|||
|
|||
const wxString CADSTAR_PCB_ARCHIVE_PLUGIN::GetFileExtension() const |
|||
{ |
|||
return wxT( "cpa" ); |
|||
} |
|||
|
|||
|
|||
BOARD* CADSTAR_PCB_ARCHIVE_PLUGIN::Load( |
|||
const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties ) |
|||
{ |
|||
m_props = aProperties; |
|||
m_board = aAppendToMe ? aAppendToMe : new BOARD(); |
|||
|
|||
CADSTAR_PCB tempPCB( m_board ); |
|||
CPA_FILE theFile( aFileName ); |
|||
theFile.Parse(); |
|||
tempPCB.Load( &theFile ); |
|||
|
|||
return m_board; |
|||
} |
|||
@ -0,0 +1,61 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2020 Roberto Fernandez Bautista <@Qbort> |
|||
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
*/ |
|||
|
|||
/** |
|||
* @file cadstar_pcb_archive_plugin.h |
|||
* @brief Pcbnew PLUGIN for CADSTAR PCB Archive (*.cpa) format: an ASCII format |
|||
* based on S-expressions. |
|||
*/ |
|||
|
|||
#ifndef CADSTAR_ARCHIVE_PLUGIN_H_ |
|||
#define CADSTAR_ARCHIVE_PLUGIN_H_ |
|||
|
|||
|
|||
#include <io_mgr.h> |
|||
|
|||
class CADSTAR_PCB_ARCHIVE_PLUGIN : public PLUGIN |
|||
{ |
|||
public: |
|||
// -----<PUBLIC PLUGIN API>-------------------------------------------------- |
|||
|
|||
const wxString PluginName() const override; |
|||
|
|||
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, |
|||
const PROPERTIES* aProperties = NULL ) override; |
|||
|
|||
const wxString GetFileExtension() const override; |
|||
|
|||
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override |
|||
{ |
|||
// No support for libraries.... |
|||
return 0; |
|||
} |
|||
|
|||
// -----</PUBLIC PLUGIN API>------------------------------------------------- |
|||
|
|||
CADSTAR_PCB_ARCHIVE_PLUGIN(); |
|||
~CADSTAR_PCB_ARCHIVE_PLUGIN(); |
|||
|
|||
private: |
|||
const PROPERTIES* m_props; |
|||
BOARD* m_board; |
|||
}; |
|||
|
|||
#endif // CADSTAR_ARCHIVE_PLUGIN_H_ |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue