ADDED: CADSTAR PCB Archive Importer

Initial commit
- Imports directly mappable layer stackup (only physical board fabrication layers for now)
This commit is contained in:
Roberto Fernandez Bautista 2020-07-12 17:58:35 +01:00 committed by Seth Hillbrand
parent 5d304cfa2a
commit 86bf592bac
19 changed files with 1394 additions and 0 deletions

View File

@ -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()
{

View File

@ -67,6 +67,7 @@ set_target_properties( cvpcb_kiface PROPERTIES
)
target_link_libraries( cvpcb_kiface
pcbcommon
cadstar2kicadpcb
3d-viewer
gal
common

View File

@ -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();

View File

@ -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

View File

@ -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 )

View File

@ -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 );
}
}

View File

@ -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_

View File

@ -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;
}

View File

@ -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_

View File

@ -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 );
}

View File

@ -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_

View File

@ -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;
}

View File

@ -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_

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -71,6 +71,7 @@ target_link_libraries( test_gal_pixel_alignment
kimath
pnsrouter
pcbcommon
cadstar2kicadpcb
bitmaps
3d-viewer
gal

View File

@ -73,6 +73,7 @@ target_link_libraries( qa_pcbnew
connectivity
pcbcommon
pnsrouter
cadstar2kicadpcb
gal
common
gal

View File

@ -53,6 +53,7 @@ target_link_libraries( qa_pcbnew_tools
connectivity
pcbcommon
pnsrouter
cadstar2kicadpcb
gal
dxflib_qcad
tinyspline_lib