ADDED: CADSTAR PCB Archive Importer
Initial commit - Imports directly mappable layer stackup (only physical board fabrication layers for now)
This commit is contained in:
parent
5d304cfa2a
commit
86bf592bac
|
@ -270,6 +270,10 @@ wxString EaglePcbFileWildcard()
|
|||
return _( "Eagle ver. 6.x XML PCB files" ) + AddFileExtListToFilter( { "brd" } );
|
||||
}
|
||||
|
||||
wxString CadstarArchivePcbFileWildcard()
|
||||
{
|
||||
return _( "CADSTAR PCB Archive files" ) + AddFileExtListToFilter( { "cpa" } );
|
||||
}
|
||||
|
||||
wxString PCadPcbFileWildcard()
|
||||
{
|
||||
|
|
|
@ -67,6 +67,7 @@ set_target_properties( cvpcb_kiface PROPERTIES
|
|||
)
|
||||
target_link_libraries( cvpcb_kiface
|
||||
pcbcommon
|
||||
cadstar2kicadpcb
|
||||
3d-viewer
|
||||
gal
|
||||
common
|
||||
|
|
|
@ -196,6 +196,7 @@ extern wxString AltiumSchematicFileWildcard();
|
|||
extern wxString EagleSchematicFileWildcard();
|
||||
extern wxString EagleFilesWildcard();
|
||||
extern wxString PCadPcbFileWildcard();
|
||||
extern wxString CadstarArchivePcbFileWildcard();
|
||||
extern wxString AltiumDesignerPcbFileWildcard();
|
||||
extern wxString AltiumCircuitStudioPcbFileWildcard();
|
||||
extern wxString AltiumCircuitMakerPcbFileWildcard();
|
||||
|
|
|
@ -596,6 +596,7 @@ endif()
|
|||
|
||||
add_subdirectory( pcad2kicadpcb_plugin )
|
||||
add_subdirectory( plugins/altium )
|
||||
add_subdirectory( cadstar2kicadpcb_plugin )
|
||||
|
||||
set( PCBNEW_IO_LIBRARIES pcad2kicadpcb altium2pcbnew CACHE INTERNAL "")
|
||||
|
||||
|
@ -692,6 +693,7 @@ set( PCBNEW_KIFACE_LIBRARIES
|
|||
connectivity
|
||||
pcbcommon
|
||||
pnsrouter
|
||||
cadstar2kicadpcb
|
||||
kiplatform
|
||||
common
|
||||
gal
|
||||
|
|
|
@ -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_
|
|
@ -89,6 +89,7 @@ bool AskLoadBoardFileName( wxWindow* aParent, int* aCtl, wxString* aFileName, bo
|
|||
{ AltiumDesignerPcbFileWildcard(), IO_MGR::ALTIUM_DESIGNER }, // Import Altium Designer board files
|
||||
{ AltiumCircuitStudioPcbFileWildcard(), IO_MGR::ALTIUM_CIRCUIT_STUDIO }, // Import Altium Circuit Studio board files
|
||||
{ AltiumCircuitMakerPcbFileWildcard(), IO_MGR::ALTIUM_CIRCUIT_MAKER }, // Import Altium Circuit Maker board files
|
||||
{ CadstarArchivePcbFileWildcard(), IO_MGR::CADSTAR_ARCHIVE }, // Import Cadstar PCB Archive board files
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
@ -388,6 +389,10 @@ IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
|
|||
{
|
||||
pluginType = IO_MGR::ALTIUM_CIRCUIT_MAKER;
|
||||
}
|
||||
else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::CADSTAR_ARCHIVE ) ) == 0 )
|
||||
{
|
||||
pluginType = IO_MGR::CADSTAR_ARCHIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pluginType = IO_MGR::KICAD_SEXP;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <wx/filename.h>
|
||||
#include <wx/uri.h>
|
||||
|
||||
#include <cadstar2kicadpcb_plugin/cadstar_pcb_archive_plugin.h>
|
||||
#include <config.h>
|
||||
#include <eagle_plugin.h>
|
||||
#include <gpcb_plugin.h>
|
||||
|
@ -215,6 +216,8 @@ static IO_MGR::REGISTER_PLUGIN registerAltiumCircuitStudioPlugin( IO_MGR::ALTIUM
|
|||
static IO_MGR::REGISTER_PLUGIN registerAltiumCircuitMakerPlugin( IO_MGR::ALTIUM_CIRCUIT_MAKER,
|
||||
wxT( "Altium Circuit Maker" ),
|
||||
[]() -> PLUGIN* { return new ALTIUM_CIRCUIT_MAKER_PLUGIN; } );
|
||||
static IO_MGR::REGISTER_PLUGIN registerCadstarArchivePlugin( IO_MGR::CADSTAR_ARCHIVE,
|
||||
wxT( "CADSTAR PCB Archive" ), []() -> PLUGIN* { return new CADSTAR_PCB_ARCHIVE_PLUGIN; } );
|
||||
#ifdef BUILD_GITHUB_PLUGIN
|
||||
static IO_MGR::REGISTER_PLUGIN registerGithubPlugin( IO_MGR::GITHUB, wxT("Github"), []() -> PLUGIN* { return new GITHUB_PLUGIN; } );
|
||||
#endif /* BUILD_GITHUB_PLUGIN */
|
||||
|
|
|
@ -60,6 +60,7 @@ public:
|
|||
ALTIUM_DESIGNER,
|
||||
ALTIUM_CIRCUIT_STUDIO,
|
||||
ALTIUM_CIRCUIT_MAKER,
|
||||
CADSTAR_ARCHIVE,
|
||||
GEDA_PCB, ///< Geda PCB file formats.
|
||||
|
||||
//N.B. This needs to be commented out to ensure compile-type errors
|
||||
|
|
|
@ -71,6 +71,7 @@ target_link_libraries( test_gal_pixel_alignment
|
|||
kimath
|
||||
pnsrouter
|
||||
pcbcommon
|
||||
cadstar2kicadpcb
|
||||
bitmaps
|
||||
3d-viewer
|
||||
gal
|
||||
|
|
|
@ -73,6 +73,7 @@ target_link_libraries( qa_pcbnew
|
|||
connectivity
|
||||
pcbcommon
|
||||
pnsrouter
|
||||
cadstar2kicadpcb
|
||||
gal
|
||||
common
|
||||
gal
|
||||
|
|
|
@ -53,6 +53,7 @@ target_link_libraries( qa_pcbnew_tools
|
|||
connectivity
|
||||
pcbcommon
|
||||
pnsrouter
|
||||
cadstar2kicadpcb
|
||||
gal
|
||||
dxflib_qcad
|
||||
tinyspline_lib
|
||||
|
|
Loading…
Reference in New Issue