ADDED: CADSTAR Parts Libraries (.lib)
This commit is contained in:
parent
8f83f27336
commit
6ab2112135
|
@ -383,8 +383,7 @@ struct MXP_LINE :
|
||||||
|
|
||||||
//[*SPI_[(<Part name>)]_[<Model>]_<Component Value>]
|
//[*SPI_[(<Part name>)]_[<Model>]_<Component Value>]
|
||||||
struct SPICE_PART_NAME : STRING_IN_BRACKETS {};
|
struct SPICE_PART_NAME : STRING_IN_BRACKETS {};
|
||||||
struct SPICE_FIRST : sor<QUOTED_STRING, STRING_EXCLUDING<WHITESPACE>> {};
|
struct SPICE_MODEL : sor<QUOTED_STRING, STRING_EXCLUDING<>> {};
|
||||||
struct SPICE_SECOND : sor<QUOTED_STRING, STRING_EXCLUDING<WHITESPACE>> {};
|
|
||||||
struct SPI_LINE :
|
struct SPI_LINE :
|
||||||
seq
|
seq
|
||||||
<
|
<
|
||||||
|
@ -392,9 +391,8 @@ struct SPI_LINE :
|
||||||
TAO_PEGTL_ISTRING( "*SPI"),
|
TAO_PEGTL_ISTRING( "*SPI"),
|
||||||
plus<WHITESPACE>,
|
plus<WHITESPACE>,
|
||||||
opt<SPICE_PART_NAME>,
|
opt<SPICE_PART_NAME>,
|
||||||
plus<WHITESPACE>,
|
star<WHITESPACE>,
|
||||||
SPICE_FIRST, // Spice Value or Model
|
SPICE_MODEL,
|
||||||
opt<plus<WHITESPACE>, SPICE_SECOND>, // Spice Value
|
|
||||||
opt<eol>
|
opt<eol>
|
||||||
>
|
>
|
||||||
{};
|
{};
|
||||||
|
|
|
@ -59,10 +59,9 @@ struct CADSTAR_PART_ENTRY
|
||||||
|
|
||||||
std::optional<std::string> m_SpicePartName;
|
std::optional<std::string> m_SpicePartName;
|
||||||
std::optional<std::string> m_SpiceModel;
|
std::optional<std::string> m_SpiceModel;
|
||||||
std::optional<std::string> m_SpiceValue;
|
|
||||||
|
|
||||||
std::optional<std::string> m_AcceptancePartName;
|
std::optional<std::string> m_AcceptancePartName; // The part the acceptance text refers to
|
||||||
std::optional<std::string> m_AcceptanceText;
|
std::optional<std::string> m_AcceptanceText; // "Part Acceptance" has canonical meaning
|
||||||
|
|
||||||
bool m_GateSwappingAllowed = true;
|
bool m_GateSwappingAllowed = true;
|
||||||
bool m_PinsVisible = true;
|
bool m_PinsVisible = true;
|
||||||
|
|
|
@ -154,26 +154,11 @@ DEFINE_STRING_ACTION( ATTRIBUTE_NAME, m_CurrentAttrName );
|
||||||
DEFINE_STRING_ACTION( ACCEPTANCE_PART_NAME, m_CurrentPart.m_AcceptancePartName );
|
DEFINE_STRING_ACTION( ACCEPTANCE_PART_NAME, m_CurrentPart.m_AcceptancePartName );
|
||||||
DEFINE_STRING_ACTION( ACCEPTANCE_TEXT, m_CurrentPart.m_AcceptanceText );
|
DEFINE_STRING_ACTION( ACCEPTANCE_TEXT, m_CurrentPart.m_AcceptanceText );
|
||||||
DEFINE_STRING_ACTION( SPICE_PART_NAME, m_CurrentPart.m_SpicePartName );
|
DEFINE_STRING_ACTION( SPICE_PART_NAME, m_CurrentPart.m_SpicePartName );
|
||||||
|
DEFINE_STRING_ACTION( SPICE_MODEL, m_CurrentPart.m_SpiceModel );
|
||||||
DEFINE_STRING_ACTION( SCH_NAME, m_CurrentSymbol.m_SymbolName );
|
DEFINE_STRING_ACTION( SCH_NAME, m_CurrentSymbol.m_SymbolName );
|
||||||
DEFINE_STRING_ACTION( SCH_ALTERNATE, m_CurrentSymbol.m_SymbolAlternateName );
|
DEFINE_STRING_ACTION( SCH_ALTERNATE, m_CurrentSymbol.m_SymbolAlternateName );
|
||||||
DEFINE_STRING_ACTION( PIN_SIGNAL_NAME, m_CurrentPin.m_Signal );
|
DEFINE_STRING_ACTION( PIN_SIGNAL_NAME, m_CurrentPin.m_Signal );
|
||||||
|
|
||||||
// Might become m_SpiceModel if SPICE_SECOND is found
|
|
||||||
DEFINE_STRING_ACTION( SPICE_FIRST, m_CurrentPart.m_SpiceValue );
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct CADSTAR_LIB_PARSER_ACTION<SPICE_SECOND>
|
|
||||||
{
|
|
||||||
/* @todo : convert to use apply0 to improve performance( once fully tested ) */
|
|
||||||
template <typename ActionInput>
|
|
||||||
static void apply( const ActionInput& in, CADSTAR_LIB_PARSER_STATE& s )
|
|
||||||
{
|
|
||||||
assert( in.string().size() >= s.m_CurrentString.size() );
|
|
||||||
s.m_CurrentPart.m_SpiceModel = s.m_CurrentPart.m_SpiceValue; // Parsed by SPICE_FIRST
|
|
||||||
s.m_CurrentPart.m_SpiceValue = s.m_CurrentString;
|
|
||||||
s.m_CurrentString = "";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// STRING SEGMENT action
|
// STRING SEGMENT action
|
||||||
// Any strings we match, append to the current state string (the state string gets
|
// Any strings we match, append to the current state string (the state string gets
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sch_plugins/cadstar/cadstar_sch_archive_loader.h>
|
#include <sch_plugins/cadstar/cadstar_sch_archive_loader.h>
|
||||||
|
#include <plugins/cadstar/cadstar_parts_lib_parser.h>
|
||||||
|
|
||||||
#include <bus_alias.h>
|
#include <bus_alias.h>
|
||||||
#include <core/mirror.h>
|
#include <core/mirror.h>
|
||||||
|
@ -46,11 +47,275 @@
|
||||||
#include <sch_sheet_pin.h>
|
#include <sch_sheet_pin.h>
|
||||||
#include <sch_label.h>
|
#include <sch_label.h>
|
||||||
#include <schematic.h>
|
#include <schematic.h>
|
||||||
|
#include <sim/sim_model.h>
|
||||||
#include <trigo.h>
|
#include <trigo.h>
|
||||||
#include <wildcards_and_files_ext.h>
|
#include <wildcards_and_files_ext.h>
|
||||||
|
|
||||||
|
|
||||||
const wxString PartNameFieldName = "Part Name";
|
const wxString PartNameFieldName = "Part Name";
|
||||||
|
const wxString PartNumberFieldName = "Part Number";
|
||||||
|
const wxString PartVersionFieldName = "Part Version";
|
||||||
|
const wxString PartAcceptanceFieldName = "Part Acceptance";
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<LIB_SYMBOL*> CADSTAR_SCH_ARCHIVE_LOADER::LoadPartsLib( const wxString& aFilename )
|
||||||
|
{
|
||||||
|
if( m_progressReporter )
|
||||||
|
m_progressReporter->SetNumPhases( 3 ); // (0) Read csa, (1) Parse csa, (3) Load lib
|
||||||
|
|
||||||
|
Parse();
|
||||||
|
|
||||||
|
CADSTAR_PARTS_LIB_PARSER p;
|
||||||
|
|
||||||
|
if( !p.CheckFileHeader( aFilename.utf8_string() ) )
|
||||||
|
THROW_IO_ERROR(
|
||||||
|
_( "The selected file does not appear to be a CADSTAR parts Library file" ) );
|
||||||
|
|
||||||
|
// TODO: we could add progress reporting for reading .lib
|
||||||
|
CADSTAR_PARTS_LIB_MODEL csLib = p.ReadFile( aFilename.utf8_string() );
|
||||||
|
|
||||||
|
if( m_progressReporter )
|
||||||
|
{
|
||||||
|
m_progressReporter->BeginPhase( 2 );
|
||||||
|
long numSteps = csLib.m_PartEntries.size();
|
||||||
|
m_progressReporter->SetMaxProgress( numSteps );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<LIB_SYMBOL*> retVal;
|
||||||
|
|
||||||
|
for( const CADSTAR_PART_ENTRY& part : csLib.m_PartEntries )
|
||||||
|
{
|
||||||
|
std::unique_ptr<LIB_SYMBOL> loadedPart = loadLibPart( part );
|
||||||
|
|
||||||
|
checkPoint();
|
||||||
|
|
||||||
|
if( loadedPart )
|
||||||
|
retVal.push_back( loadedPart.release() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<LIB_SYMBOL>
|
||||||
|
CADSTAR_SCH_ARCHIVE_LOADER::loadLibPart( const CADSTAR_PART_ENTRY& aPart )
|
||||||
|
{
|
||||||
|
wxString escapedPartName = EscapeString( aPart.m_Name, CTX_LIBID );
|
||||||
|
std::unique_ptr<LIB_SYMBOL> retSym;
|
||||||
|
|
||||||
|
int unit = 0;
|
||||||
|
|
||||||
|
for( const CADSTAR_PART_SYMBOL_ENTRY& sym : aPart.m_Symbols )
|
||||||
|
{
|
||||||
|
++unit;
|
||||||
|
wxString alternateName = sym.m_SymbolAlternateName.value_or( "" );
|
||||||
|
SYMDEF_ID symbolID = getSymDefFromName( sym.m_SymbolName, alternateName );
|
||||||
|
|
||||||
|
if( !Library.SymbolDefinitions.count( symbolID ) )
|
||||||
|
{
|
||||||
|
m_reporter->Report(
|
||||||
|
wxString::Format( _( "Unable to find symbol %s, referenced by part %s. The "
|
||||||
|
"part was not loaded." ),
|
||||||
|
generateLibName( sym.m_SymbolName, alternateName ),
|
||||||
|
aPart.m_Name ),
|
||||||
|
RPT_SEVERITY_ERROR );
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the graphical symbol for this gate
|
||||||
|
std::unique_ptr<LIB_SYMBOL> kiSymDef( loadSymdef( symbolID )->Duplicate() );
|
||||||
|
|
||||||
|
if( sym.m_Pins.size() != kiSymDef->GetPinCount() )
|
||||||
|
{
|
||||||
|
m_reporter->Report(
|
||||||
|
wxString::Format( _( "Inconsitent pin numbers in symbol %s compared to the one "
|
||||||
|
"defined in part %s. The part was not loaded." ),
|
||||||
|
generateLibName( sym.m_SymbolName, alternateName ),
|
||||||
|
aPart.m_Name ),
|
||||||
|
RPT_SEVERITY_ERROR );
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxASSERT( m_symDefTerminalsMap.count( symbolID ) ); //loadSymDef should have populated this
|
||||||
|
|
||||||
|
|
||||||
|
// Update the pin numbers to match those defined in the Cadstar part
|
||||||
|
for( auto& [storedPinNum, termID] : m_symDefTerminalsMap[symbolID] )
|
||||||
|
{
|
||||||
|
wxCHECK( termID > 0 && sym.m_Pins.size() >= termID, nullptr );
|
||||||
|
LIB_PIN* pin = kiSymDef->GetPin( storedPinNum );
|
||||||
|
size_t termIdx = size_t( termID ) - 1;
|
||||||
|
|
||||||
|
// For now leave numerical pin number. Otherwise, when loading the
|
||||||
|
// .cpa file we won't be able to link up to the footprint pads, but if
|
||||||
|
// we solve this, we could then load alphanumeric pin numbers as below:
|
||||||
|
//
|
||||||
|
// if( aPart.m_PinNamesMap.count( termID ) )
|
||||||
|
// partPinNum = wxString( aPart.m_PinNamesMap.at( termID ) );
|
||||||
|
//
|
||||||
|
wxString partPinNum = wxString::Format( "%ld", sym.m_Pins[termIdx].m_Identifier );
|
||||||
|
pin->SetNumber( partPinNum );
|
||||||
|
|
||||||
|
if( aPart.m_PinNamesMap.count( termID ) )
|
||||||
|
pin->SetName( HandleTextOverbar( aPart.m_PinNamesMap.at( termID ) ) );
|
||||||
|
|
||||||
|
pin->SetType( getKiCadPinType( sym.m_Pins[termIdx].m_Type ) );
|
||||||
|
|
||||||
|
// @todo: Load pin/gate swapping information once kicad supports this
|
||||||
|
}
|
||||||
|
|
||||||
|
if( unit == 1 )
|
||||||
|
{
|
||||||
|
wxCHECK( kiSymDef->GetUnitCount() == 1, nullptr );
|
||||||
|
// The first unit can just be moved to the part symbol
|
||||||
|
retSym = std::move( kiSymDef );
|
||||||
|
|
||||||
|
retSym->SetUnitCount( aPart.m_Symbols.size(), true );
|
||||||
|
|
||||||
|
retSym->SetName( escapedPartName );
|
||||||
|
retSym->GetReferenceField().SetText( aPart.m_ComponentStem );
|
||||||
|
retSym->GetValueField().SetText( aPart.m_Value.value_or( "" ) );
|
||||||
|
addNewFieldToSymbol( PartNameFieldName, retSym )->SetText( aPart.m_Name );
|
||||||
|
retSym->SetDescription( aPart.m_Description.value_or( "" ) );
|
||||||
|
|
||||||
|
auto addFieldIfHasValue =
|
||||||
|
[&]( const wxString& aFieldName, const std::optional<std::string>& aFieldValue )
|
||||||
|
{
|
||||||
|
if( aFieldValue.has_value() )
|
||||||
|
addNewFieldToSymbol( aFieldName, retSym )->SetText( aFieldValue.value() );
|
||||||
|
};
|
||||||
|
|
||||||
|
addFieldIfHasValue( PartNumberFieldName, aPart.m_Number );
|
||||||
|
addFieldIfHasValue( PartVersionFieldName, aPart.m_Version );
|
||||||
|
addFieldIfHasValue( PartAcceptanceFieldName, aPart.m_AcceptancePartName );
|
||||||
|
|
||||||
|
setFootprintOnSymbol( retSym, aPart.m_Pcb_component,
|
||||||
|
aPart.m_Pcb_alternate.value_or( "" ) );
|
||||||
|
|
||||||
|
if(aPart.m_SpiceModel.has_value())
|
||||||
|
{
|
||||||
|
wxString modelVal = wxString::Format( "model=\"%s\"", aPart.m_SpiceModel.value() );
|
||||||
|
addNewFieldToSymbol( SIM_DEVICE_TYPE_FIELD, retSym )->SetText( "SPICE" );
|
||||||
|
addNewFieldToSymbol( SIM_PARAMS_FIELD, retSym )->SetText( modelVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load all part attributes, regardless of original cadstar type, to the symbol
|
||||||
|
|
||||||
|
// @todo some cadstar part attributes have a "read-only" flag. We should load this
|
||||||
|
// when KiCad supports read-only fields.
|
||||||
|
|
||||||
|
for( auto& [fieldName, value] : aPart.m_UserAttributes )
|
||||||
|
addNewFieldToSymbol( fieldName, retSym )->SetText( value );
|
||||||
|
|
||||||
|
for( auto& [fieldName, attrValue] : aPart.m_SchAttributes )
|
||||||
|
addNewFieldToSymbol( fieldName, retSym )->SetText( attrValue.m_Value );
|
||||||
|
|
||||||
|
for( auto& [fieldName, attrValue] : aPart.m_PcbAttributes )
|
||||||
|
addNewFieldToSymbol( fieldName, retSym )->SetText( attrValue.m_Value );
|
||||||
|
|
||||||
|
for( auto& [fieldName, attrValue] : aPart.m_SchAndPcbAttributes )
|
||||||
|
addNewFieldToSymbol( fieldName, retSym )->SetText( attrValue.m_Value );
|
||||||
|
|
||||||
|
for( auto& [fieldName, attrValue] : aPart.m_PartAttributes )
|
||||||
|
addNewFieldToSymbol( fieldName, retSym )->SetText( attrValue.m_Value );
|
||||||
|
|
||||||
|
// Load all hidden pins onto the first unit of the symbol in KiCad
|
||||||
|
// We load them in a spiral sequence, starting at the center of the symbol BBOX
|
||||||
|
VECTOR2I symCenter = retSym->GetBodyBoundingBox( unit, 0, false, false ).GetCenter();
|
||||||
|
symCenter.y = -symCenter.y; // need to invert the y coord for lib symbols.
|
||||||
|
|
||||||
|
VECTOR2I delta( 0, 1 );
|
||||||
|
VECTOR2I direction( 0, -1 );
|
||||||
|
int spacing = schIUScale.MilsToIU( 50 ); // for now, place on a 50mil grid
|
||||||
|
|
||||||
|
for( const CADSTAR_PART_PIN& csPin : aPart.m_HiddenPins )
|
||||||
|
{
|
||||||
|
std::unique_ptr<LIB_PIN> pin = std::make_unique<LIB_PIN>( retSym.get() );
|
||||||
|
|
||||||
|
long pinNum = csPin.m_Identifier;
|
||||||
|
pin->SetNumber( wxString::Format( "%ld", pinNum ) );
|
||||||
|
|
||||||
|
if( csPin.m_Signal.has_value() )
|
||||||
|
{
|
||||||
|
// Implied net connection
|
||||||
|
pin->SetName( csPin.m_Signal.value() );
|
||||||
|
pin->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN );
|
||||||
|
}
|
||||||
|
else if( aPart.m_PinNamesMap.count( pinNum ) )
|
||||||
|
{
|
||||||
|
pin->SetName( HandleTextOverbar( aPart.m_PinNamesMap.at( pinNum ) ) );
|
||||||
|
pin->SetType( getKiCadPinType( csPin.m_Type ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
pin->SetVisible( false );
|
||||||
|
|
||||||
|
// Generate the coordinate for the pin. We don't want overlapping pins
|
||||||
|
// and ideally close to the center of the symbol, so we load pins sequentially
|
||||||
|
// in a spiral sequence
|
||||||
|
if( delta.x == delta.y
|
||||||
|
|| ( delta.x < 0 && delta.x == -delta.y )
|
||||||
|
|| ( delta.x > 0 && delta.x == 1 - delta.y ) )
|
||||||
|
{
|
||||||
|
// change direction
|
||||||
|
direction = { -direction.y, direction.x };
|
||||||
|
}
|
||||||
|
|
||||||
|
delta += direction;
|
||||||
|
VECTOR2I offset = delta * spacing;
|
||||||
|
pin->SetPosition( symCenter + offset );
|
||||||
|
pin->SetLength( 0 ); //CADSTAR Pins are just a point (have no length)
|
||||||
|
pin->SetShape( GRAPHIC_PINSHAPE::LINE );
|
||||||
|
pin->SetUnit( unit );
|
||||||
|
retSym->AddDrawItem( pin.release() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Source: Dest:
|
||||||
|
copySymbolItems( kiSymDef, retSym, unit, false /* aOverrideFields */ );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
retSym->SetShowPinNames( aPart.m_PinsVisible );
|
||||||
|
retSym->SetShowPinNumbers( aPart.m_PinsVisible );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return retSym;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CADSTAR_SCH_ARCHIVE_LOADER::copySymbolItems( std::unique_ptr<LIB_SYMBOL>& aSourceSym,
|
||||||
|
std::unique_ptr<LIB_SYMBOL>& aDestSym,
|
||||||
|
int aDestUnit, bool aOverrideFields )
|
||||||
|
{
|
||||||
|
// Ensure there are no items on the unit we want to load onto
|
||||||
|
for( LIB_ITEM* item : aDestSym->GetUnitDrawItems( aDestUnit, 0 /*aConvert*/ ) )
|
||||||
|
aDestSym->RemoveDrawItem( item );
|
||||||
|
|
||||||
|
// Copy all draw items
|
||||||
|
for( LIB_ITEM* newItem : aSourceSym->GetUnitDrawItems( 1, 0 /*aConvert*/ ) )
|
||||||
|
{
|
||||||
|
LIB_ITEM* itemCopy = static_cast<LIB_ITEM*>( newItem->Clone() );
|
||||||
|
itemCopy->SetParent( aDestSym.get() );
|
||||||
|
itemCopy->SetUnit( aDestUnit );
|
||||||
|
aDestSym->AddDrawItem( itemCopy );
|
||||||
|
}
|
||||||
|
|
||||||
|
//Copy / override all fields
|
||||||
|
if( aOverrideFields )
|
||||||
|
{
|
||||||
|
std::vector<LIB_FIELD*> fieldsToCopy;
|
||||||
|
aSourceSym->GetFields( fieldsToCopy );
|
||||||
|
|
||||||
|
for( LIB_FIELD* templateField : fieldsToCopy )
|
||||||
|
{
|
||||||
|
LIB_FIELD* appliedField = addNewFieldToSymbol( templateField->GetName(), aDestSym );
|
||||||
|
templateField->Copy( appliedField );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CADSTAR_SCH_ARCHIVE_LOADER::Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet )
|
void CADSTAR_SCH_ARCHIVE_LOADER::Load( SCHEMATIC* aSchematic, SCH_SHEET* aRootSheet )
|
||||||
|
@ -386,9 +651,9 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadPartsLibrary()
|
||||||
PART part = partPair.second;
|
PART part = partPair.second;
|
||||||
|
|
||||||
wxString escapedPartName = EscapeString( part.Name, CTX_LIBID );
|
wxString escapedPartName = EscapeString( part.Name, CTX_LIBID );
|
||||||
LIB_SYMBOL* kiPart = new LIB_SYMBOL( escapedPartName );
|
LIB_SYMBOL* kiSym = new LIB_SYMBOL( escapedPartName );
|
||||||
|
|
||||||
kiPart->SetUnitCount( part.Definition.GateSymbols.size() );
|
kiSym->SetUnitCount( part.Definition.GateSymbols.size() );
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|
||||||
for( std::pair<GATE_ID, PART::DEFINITION::GATE> gatePair : part.Definition.GateSymbols )
|
for( std::pair<GATE_ID, PART::DEFINITION::GATE> gatePair : part.Definition.GateSymbols )
|
||||||
|
@ -413,12 +678,12 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadPartsLibrary()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_partSymbolsMap.insert( { { partID, gateID }, symbolID } );
|
m_partSymbolsMap.insert( { { partID, gateID }, symbolID } );
|
||||||
loadSymbolGateAndPartFields( symbolID, &part, gateID, kiPart );
|
loadSymbolGateAndPartFields( symbolID, part, gateID, kiSym );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ok && part.Definition.GateSymbols.size() != 0 )
|
if( ok && part.Definition.GateSymbols.size() != 0 )
|
||||||
{
|
{
|
||||||
m_loadedSymbols.push_back( kiPart );
|
m_loadedSymbols.push_back( kiSym );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -437,7 +702,7 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadPartsLibrary()
|
||||||
// the part name, which is important to load
|
// the part name, which is important to load
|
||||||
}
|
}
|
||||||
|
|
||||||
m_partMap.insert( { partID, kiPart } );
|
m_partMap.insert( { partID, kiSym } );
|
||||||
|
|
||||||
checkPoint();
|
checkPoint();
|
||||||
}
|
}
|
||||||
|
@ -471,7 +736,7 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadSchematicSymbolInstances()
|
||||||
sym.GateID = wxT( "A" ); // Assume Gate "A" if unspecified
|
sym.GateID = wxT( "A" ); // Assume Gate "A" if unspecified
|
||||||
|
|
||||||
PART_GATE_ID partSymbolID = { sym.PartRef.RefID, sym.GateID };
|
PART_GATE_ID partSymbolID = { sym.PartRef.RefID, sym.GateID };
|
||||||
LIB_SYMBOL* kiPart = m_partMap.at( sym.PartRef.RefID );
|
LIB_SYMBOL* kiSym = m_partMap.at( sym.PartRef.RefID );
|
||||||
bool copy = false;
|
bool copy = false;
|
||||||
|
|
||||||
// The symbol definition in the part either does not exist for this gate number
|
// The symbol definition in the part either does not exist for this gate number
|
||||||
|
@ -480,13 +745,13 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadSchematicSymbolInstances()
|
||||||
if( m_partSymbolsMap.find( partSymbolID ) == m_partSymbolsMap.end()
|
if( m_partSymbolsMap.find( partSymbolID ) == m_partSymbolsMap.end()
|
||||||
|| m_partSymbolsMap.at( partSymbolID ) != sym.SymdefID )
|
|| m_partSymbolsMap.at( partSymbolID ) != sym.SymdefID )
|
||||||
{
|
{
|
||||||
kiPart = new LIB_SYMBOL( *kiPart ); // Make a copy
|
kiSym = new LIB_SYMBOL( *kiSym ); // Make a copy
|
||||||
copy = true;
|
copy = true;
|
||||||
const PART& part = Parts.PartDefinitions.at( sym.PartRef.RefID );
|
const PART& part = Parts.PartDefinitions.at( sym.PartRef.RefID );
|
||||||
loadSymbolGateAndPartFields( sym.SymdefID, &part, sym.GateID, kiPart );
|
loadSymbolGateAndPartFields( sym.SymdefID, part, sym.GateID, kiSym );
|
||||||
}
|
}
|
||||||
|
|
||||||
LIB_SYMBOL* scaledPart = getScaledLibPart( kiPart, sym.ScaleRatioNumerator,
|
LIB_SYMBOL* scaledPart = getScaledLibPart( kiSym, sym.ScaleRatioNumerator,
|
||||||
sym.ScaleRatioDenominator );
|
sym.ScaleRatioDenominator );
|
||||||
|
|
||||||
EDA_ANGLE symOrient = ANGLE_0;
|
EDA_ANGLE symOrient = ANGLE_0;
|
||||||
|
@ -495,7 +760,7 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadSchematicSymbolInstances()
|
||||||
delete scaledPart;
|
delete scaledPart;
|
||||||
|
|
||||||
if( copy )
|
if( copy )
|
||||||
delete kiPart;
|
delete kiSym;
|
||||||
|
|
||||||
SCH_FIELD* refField = symbol->GetField( REFERENCE_FIELD );
|
SCH_FIELD* refField = symbol->GetField( REFERENCE_FIELD );
|
||||||
|
|
||||||
|
@ -1320,16 +1585,28 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadTextVariables()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LIB_FIELD* CADSTAR_SCH_ARCHIVE_LOADER::addNewFieldToSymbol( const wxString& aFieldName,
|
LIB_FIELD*
|
||||||
LIB_SYMBOL* aKiCadSymbol )
|
CADSTAR_SCH_ARCHIVE_LOADER::addNewFieldToSymbol( const wxString& aFieldName,
|
||||||
|
std::unique_ptr<LIB_SYMBOL>& aKiCadSymbol )
|
||||||
{
|
{
|
||||||
int fieldID = aKiCadSymbol->GetFieldCount();
|
// First Check if field already exists
|
||||||
LIB_FIELD* field = new LIB_FIELD( aKiCadSymbol, fieldID );
|
LIB_FIELD* existingField = aKiCadSymbol->FindField( aFieldName );
|
||||||
field->SetName( aFieldName );
|
|
||||||
field->SetVisible( false );
|
|
||||||
aKiCadSymbol->AddField( field );
|
|
||||||
|
|
||||||
return field;
|
if( existingField != nullptr )
|
||||||
|
return existingField;
|
||||||
|
|
||||||
|
int newfieldID = aKiCadSymbol->GetFieldCount();
|
||||||
|
LIB_FIELD* newfield = new LIB_FIELD( aKiCadSymbol.get(), newfieldID );
|
||||||
|
newfield->SetName( aFieldName );
|
||||||
|
newfield->SetVisible( false );
|
||||||
|
aKiCadSymbol->AddField( newfield );
|
||||||
|
/*
|
||||||
|
@todo we should load that a field is a URL by checking if it starts with "Link"
|
||||||
|
e.g.:
|
||||||
|
if( aFieldName.Lower().StartsWith( "link" ) )
|
||||||
|
newfield->SetAsURL*/
|
||||||
|
|
||||||
|
return newfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1485,7 +1762,7 @@ const LIB_SYMBOL* CADSTAR_SCH_ARCHIVE_LOADER::loadSymdef( const SYMDEF_ID& aSymd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always add the part name field (even if it doesn't have a specific location defined)
|
// Always add the part name field (even if it doesn't have a specific location defined)
|
||||||
addNewFieldToSymbol( PartNameFieldName, kiSym.get() );
|
addNewFieldToSymbol( PartNameFieldName, kiSym );
|
||||||
|
|
||||||
if( csSym.TextLocations.count( PART_NAME_ATTRID ) )
|
if( csSym.TextLocations.count( PART_NAME_ATTRID ) )
|
||||||
{
|
{
|
||||||
|
@ -1509,7 +1786,7 @@ const LIB_SYMBOL* CADSTAR_SCH_ARCHIVE_LOADER::loadSymdef( const SYMDEF_ID& aSymd
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString attributeName = getAttributeName( attributeId );
|
wxString attributeName = getAttributeName( attributeId );
|
||||||
LIB_FIELD* field = addNewFieldToSymbol( attributeName, kiSym.get() );
|
LIB_FIELD* field = addNewFieldToSymbol( attributeName, kiSym );
|
||||||
applyToLibraryFieldAttribute( textLocation, csSym.Origin, field );
|
applyToLibraryFieldAttribute( textLocation, csSym.Origin, field );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1523,7 +1800,7 @@ const LIB_SYMBOL* CADSTAR_SCH_ARCHIVE_LOADER::loadSymdef( const SYMDEF_ID& aSymd
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString attributeName = getAttributeName( attributeId );
|
wxString attributeName = getAttributeName( attributeId );
|
||||||
LIB_FIELD* field = addNewFieldToSymbol( attributeName, kiSym.get() );
|
LIB_FIELD* field = addNewFieldToSymbol( attributeName, kiSym );
|
||||||
|
|
||||||
if( attrValue.HasLocation )
|
if( attrValue.HasLocation )
|
||||||
applyToLibraryFieldAttribute( attrValue.AttributeLocation, csSym.Origin, field );
|
applyToLibraryFieldAttribute( attrValue.AttributeLocation, csSym.Origin, field );
|
||||||
|
@ -1537,7 +1814,7 @@ const LIB_SYMBOL* CADSTAR_SCH_ARCHIVE_LOADER::loadSymdef( const SYMDEF_ID& aSymd
|
||||||
|
|
||||||
|
|
||||||
void CADSTAR_SCH_ARCHIVE_LOADER::loadSymbolGateAndPartFields( const SYMDEF_ID& aSymdefID,
|
void CADSTAR_SCH_ARCHIVE_LOADER::loadSymbolGateAndPartFields( const SYMDEF_ID& aSymdefID,
|
||||||
const PART* aCadstarPart,
|
const PART& aCadstarPart,
|
||||||
const GATE_ID& aGateID,
|
const GATE_ID& aGateID,
|
||||||
LIB_SYMBOL* aSymbol )
|
LIB_SYMBOL* aSymbol )
|
||||||
{
|
{
|
||||||
|
@ -1546,179 +1823,156 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadSymbolGateAndPartFields( const SYMDEF_ID& a
|
||||||
std::unique_ptr<LIB_SYMBOL> kiSymDef( loadSymdef( aSymdefID )->Duplicate() );
|
std::unique_ptr<LIB_SYMBOL> kiSymDef( loadSymdef( aSymdefID )->Duplicate() );
|
||||||
wxCHECK( kiSymDef, /*void*/ );
|
wxCHECK( kiSymDef, /*void*/ );
|
||||||
|
|
||||||
if( aCadstarPart )
|
//todo: need to use unique_ptr more. For now just create it here and release at end of function
|
||||||
|
std::unique_ptr<LIB_SYMBOL> tempSymbol( aSymbol );
|
||||||
|
|
||||||
|
// Update the pin numbers to match those defined in the Cadstar part
|
||||||
|
TERMINAL_TO_PINNUM_MAP pinNumMap;
|
||||||
|
|
||||||
|
for( auto&& [storedPinNum, termID] : m_symDefTerminalsMap[aSymdefID] )
|
||||||
{
|
{
|
||||||
// Update the pin numbers to match those defined in the Cadstar part
|
PART::DEFINITION::PIN csPin = getPartDefinitionPin( aCadstarPart, aGateID, termID );
|
||||||
|
LIB_PIN* pin = kiSymDef->GetPin( storedPinNum );
|
||||||
|
|
||||||
TERMINAL_TO_PINNUM_MAP pinNumMap;
|
wxString pinName = HandleTextOverbar( csPin.Label );
|
||||||
|
wxString pinNum = HandleTextOverbar( csPin.Name );
|
||||||
|
|
||||||
for( auto&& [storedPinNum, termID] : m_symDefTerminalsMap[aSymdefID] )
|
if( pinNum.IsEmpty() )
|
||||||
{
|
{
|
||||||
PART::DEFINITION::PIN csPin = getPartDefinitionPin( *aCadstarPart, aGateID, termID );
|
if( !csPin.Identifier.IsEmpty() )
|
||||||
LIB_PIN* pin = kiSymDef->GetPin( storedPinNum );
|
pinNum = csPin.Identifier;
|
||||||
|
else if( csPin.ID == UNDEFINED_VALUE )
|
||||||
wxString pinName = HandleTextOverbar( csPin.Label );
|
pinNum = wxString::Format( "%ld", termID );
|
||||||
wxString pinNum = HandleTextOverbar( csPin.Name );
|
else
|
||||||
|
pinNum = wxString::Format( "%ld", csPin.ID );
|
||||||
if( pinNum.IsEmpty() )
|
|
||||||
{
|
|
||||||
if( !csPin.Identifier.IsEmpty() )
|
|
||||||
pinNum = csPin.Identifier;
|
|
||||||
else if( csPin.ID == UNDEFINED_VALUE )
|
|
||||||
pinNum = wxString::Format( "%ld", termID );
|
|
||||||
else
|
|
||||||
pinNum = wxString::Format( "%ld", csPin.ID );
|
|
||||||
}
|
|
||||||
|
|
||||||
pin->SetType( getKiCadPinType( csPin.Type ) );
|
|
||||||
pin->SetNumber( pinNum );
|
|
||||||
pin->SetName( pinName );
|
|
||||||
|
|
||||||
pinNumMap.insert( { termID, pinNum } );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pinNumsMap.insert( { aCadstarPart->ID + aGateID, pinNumMap } );
|
pin->SetType( getKiCadPinType( csPin.Type ) );
|
||||||
|
pin->SetNumber( pinNum );
|
||||||
|
pin->SetName( pinName );
|
||||||
|
|
||||||
|
pinNumMap.insert( { termID, pinNum } );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_pinNumsMap.insert( { aCadstarPart.ID + aGateID, pinNumMap } );
|
||||||
|
|
||||||
// COPY ITEMS
|
// COPY ITEMS
|
||||||
// Copy the items over to aSymbol
|
|
||||||
int gateNumber = getKiCadUnitNumberFromGate( aGateID );
|
int gateNumber = getKiCadUnitNumberFromGate( aGateID );
|
||||||
|
copySymbolItems( kiSymDef, tempSymbol, gateNumber );
|
||||||
// Ensure there are no items on the unit we want to load onto
|
|
||||||
for( LIB_ITEM* item : aSymbol->GetUnitDrawItems( gateNumber, 0 /*aConvert*/ ) )
|
|
||||||
aSymbol->RemoveDrawItem( item );
|
|
||||||
|
|
||||||
// Copy all draw items
|
|
||||||
for( LIB_ITEM* newItem : kiSymDef->GetUnitDrawItems( 1, 0 /*aConvert*/ ) )
|
|
||||||
{
|
|
||||||
LIB_ITEM* itemCopy = static_cast<LIB_ITEM*>( newItem->Clone() );
|
|
||||||
itemCopy->SetParent( aSymbol );
|
|
||||||
itemCopy->SetUnit( gateNumber );
|
|
||||||
aSymbol->AddDrawItem( itemCopy );
|
|
||||||
}
|
|
||||||
|
|
||||||
//Copy / override all fields
|
|
||||||
std::vector<LIB_FIELD*> fieldsToCopy;
|
|
||||||
kiSymDef->GetFields( fieldsToCopy );
|
|
||||||
|
|
||||||
for( LIB_FIELD* templateField : fieldsToCopy )
|
|
||||||
{
|
|
||||||
LIB_FIELD* appliedField = aSymbol->FindField( templateField->GetName() );
|
|
||||||
|
|
||||||
if( !appliedField )
|
|
||||||
appliedField = addNewFieldToSymbol( templateField->GetName(), aSymbol );
|
|
||||||
|
|
||||||
|
|
||||||
templateField->Copy( appliedField );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide the value field for now (it might get unhidden if an attribute exists in the cadstar
|
// Hide the value field for now (it might get unhidden if an attribute exists in the cadstar
|
||||||
// design with the text "Value"
|
// design with the text "Value"
|
||||||
aSymbol->GetValueField().SetVisible( false );
|
tempSymbol->GetValueField().SetVisible( false );
|
||||||
|
|
||||||
|
|
||||||
if( aCadstarPart )
|
LIB_FIELD* partNameField = tempSymbol->FindField( PartNameFieldName );
|
||||||
|
|
||||||
|
if( partNameField )
|
||||||
|
partNameField->SetText( EscapeFieldText( aCadstarPart.Name ) );
|
||||||
|
|
||||||
|
const POINT& symDefOrigin = Library.SymbolDefinitions.at( aSymdefID ).Origin;
|
||||||
|
wxString footprintRefName = wxEmptyString;
|
||||||
|
wxString footprintAlternateName = wxEmptyString;
|
||||||
|
|
||||||
|
auto loadLibraryField = [&]( const ATTRIBUTE_VALUE& aAttributeVal )
|
||||||
{
|
{
|
||||||
LIB_FIELD* partNameField = aSymbol->FindField( PartNameFieldName );
|
wxString attrName = getAttributeName( aAttributeVal.AttributeID );
|
||||||
|
|
||||||
if( partNameField )
|
// Remove invalid field characters
|
||||||
partNameField->SetText( EscapeFieldText( aCadstarPart->Name ) );
|
wxString attributeValue = aAttributeVal.Value;
|
||||||
|
attributeValue.Replace( wxT( "\n" ), wxT( "\\n" ) );
|
||||||
|
attributeValue.Replace( wxT( "\r" ), wxT( "\\r" ) );
|
||||||
|
attributeValue.Replace( wxT( "\t" ), wxT( "\\t" ) );
|
||||||
|
|
||||||
const POINT& symDefOrigin = Library.SymbolDefinitions.at( aSymdefID ).Origin;
|
//TODO: Handle "links": In cadstar a field can be a "link" if its name starts
|
||||||
wxString footprintRefName = wxEmptyString;
|
// with the characters "Link ". Need to figure out how to convert them to
|
||||||
wxString footprintAlternateName = wxEmptyString;
|
// equivalent in KiCad.
|
||||||
|
|
||||||
auto loadLibraryField = [&]( const ATTRIBUTE_VALUE& aAttributeVal )
|
if( attrName == wxT( "(PartDefinitionNameStem)" ) )
|
||||||
{
|
{
|
||||||
wxString attrName = getAttributeName( aAttributeVal.AttributeID );
|
//Space not allowed in Reference field
|
||||||
|
attributeValue.Replace( wxT( " " ), "_" );
|
||||||
// Remove invalid field characters
|
tempSymbol->GetReferenceField().SetText( attributeValue );
|
||||||
wxString attributeValue = aAttributeVal.Value;
|
return;
|
||||||
attributeValue.Replace( wxT( "\n" ), wxT( "\\n" ) );
|
}
|
||||||
attributeValue.Replace( wxT( "\r" ), wxT( "\\r" ) );
|
else if( attrName == wxT( "(PartDescription)" ) )
|
||||||
attributeValue.Replace( wxT( "\t" ), wxT( "\\t" ) );
|
|
||||||
|
|
||||||
//TODO: Handle "links": In cadstar a field can be a "link" if its name starts
|
|
||||||
// with the characters "Link ". Need to figure out how to convert them to
|
|
||||||
// equivalent in KiCad.
|
|
||||||
|
|
||||||
if( attrName == wxT( "(PartDefinitionNameStem)" ) )
|
|
||||||
{
|
|
||||||
//Space not allowed in Reference field
|
|
||||||
attributeValue.Replace( wxT( " " ), "_" );
|
|
||||||
aSymbol->GetReferenceField().SetText( attributeValue );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if( attrName == wxT( "(PartDescription)" ) )
|
|
||||||
{
|
|
||||||
aSymbol->SetDescription( attributeValue );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if( attrName == wxT( "(PartDefinitionReferenceName)" ) )
|
|
||||||
{
|
|
||||||
footprintRefName = attributeValue;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if( attrName == wxT( "(PartDefinitionAlternateName)" ) )
|
|
||||||
{
|
|
||||||
footprintAlternateName = attributeValue;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LIB_FIELD* attrField = aSymbol->FindField( attrName );
|
|
||||||
bool existsInSymbol = attrField != nullptr;
|
|
||||||
|
|
||||||
if( !attrField )
|
|
||||||
attrField = addNewFieldToSymbol( attrName, aSymbol );
|
|
||||||
|
|
||||||
wxASSERT( attrField->GetName() == attrName );
|
|
||||||
attrField->SetText( aAttributeVal.Value );
|
|
||||||
attrField->SetUnit( gateNumber );
|
|
||||||
|
|
||||||
const ATTRIBUTE_ID& attrid = aAttributeVal.AttributeID;
|
|
||||||
attrField->SetVisible( isAttributeVisible( attrid ) );
|
|
||||||
|
|
||||||
if( aAttributeVal.HasLocation )
|
|
||||||
{
|
|
||||||
// Check if the part itself defined a location for the field
|
|
||||||
applyToLibraryFieldAttribute( aAttributeVal.AttributeLocation, symDefOrigin,
|
|
||||||
attrField );
|
|
||||||
}
|
|
||||||
else if( !existsInSymbol )
|
|
||||||
{
|
|
||||||
attrField->SetVisible( false );
|
|
||||||
applyTextSettings( attrField, wxT( "TC1" ), ALIGNMENT::NO_ALIGNMENT,
|
|
||||||
JUSTIFICATION::LEFT );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load all attributes in the Part Definition
|
|
||||||
for( auto& [attrId, attrVal] : aCadstarPart->Definition.AttributeValues )
|
|
||||||
loadLibraryField( attrVal );
|
|
||||||
|
|
||||||
// Load all attributes in the Part itself.
|
|
||||||
for( auto& [attrId, attrVal] : aCadstarPart->AttributeValues )
|
|
||||||
loadLibraryField( attrVal );
|
|
||||||
|
|
||||||
wxString fpNameInLibrary = generateLibName( footprintRefName, footprintAlternateName );
|
|
||||||
|
|
||||||
if( !fpNameInLibrary.IsEmpty() )
|
|
||||||
{
|
{
|
||||||
wxArrayString fpFilters;
|
tempSymbol->SetDescription( attributeValue );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if( attrName == wxT( "(PartDefinitionReferenceName)" ) )
|
||||||
|
{
|
||||||
|
footprintRefName = attributeValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if( attrName == wxT( "(PartDefinitionAlternateName)" ) )
|
||||||
|
{
|
||||||
|
footprintAlternateName = attributeValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool attrIsNew = tempSymbol->FindField( attrName ) == nullptr;
|
||||||
|
LIB_FIELD* attrField = addNewFieldToSymbol( attrName, tempSymbol );
|
||||||
|
|
||||||
|
wxASSERT( attrField->GetName() == attrName );
|
||||||
|
attrField->SetText( aAttributeVal.Value );
|
||||||
|
attrField->SetUnit( gateNumber );
|
||||||
|
|
||||||
|
const ATTRIBUTE_ID& attrid = aAttributeVal.AttributeID;
|
||||||
|
attrField->SetVisible( isAttributeVisible( attrid ) );
|
||||||
|
|
||||||
|
if( aAttributeVal.HasLocation )
|
||||||
|
{
|
||||||
|
// Check if the part itself defined a location for the field
|
||||||
|
applyToLibraryFieldAttribute( aAttributeVal.AttributeLocation, symDefOrigin,
|
||||||
|
attrField );
|
||||||
|
}
|
||||||
|
else if( attrIsNew )
|
||||||
|
{
|
||||||
|
attrField->SetVisible( false );
|
||||||
|
applyTextSettings( attrField, wxT( "TC1" ), ALIGNMENT::NO_ALIGNMENT,
|
||||||
|
JUSTIFICATION::LEFT );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load all attributes in the Part Definition
|
||||||
|
for( auto& [attrId, attrVal] : aCadstarPart.Definition.AttributeValues )
|
||||||
|
loadLibraryField( attrVal );
|
||||||
|
|
||||||
|
// Load all attributes in the Part itself.
|
||||||
|
for( auto& [attrId, attrVal] : aCadstarPart.AttributeValues )
|
||||||
|
loadLibraryField( attrVal );
|
||||||
|
|
||||||
|
setFootprintOnSymbol( tempSymbol, footprintRefName, footprintAlternateName );
|
||||||
|
|
||||||
|
if( aCadstarPart.Definition.HidePinNames )
|
||||||
|
{
|
||||||
|
tempSymbol->SetShowPinNames( false );
|
||||||
|
tempSymbol->SetShowPinNumbers( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
aSymbol = tempSymbol.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CADSTAR_SCH_ARCHIVE_LOADER::setFootprintOnSymbol( std::unique_ptr<LIB_SYMBOL>& aKiCadSymbol,
|
||||||
|
const wxString& aFootprintName,
|
||||||
|
const wxString& aFootprintAlternate )
|
||||||
|
{
|
||||||
|
wxString fpNameInLibrary = generateLibName( aFootprintName, aFootprintAlternate );
|
||||||
|
|
||||||
|
if( !fpNameInLibrary.IsEmpty() )
|
||||||
|
{
|
||||||
|
wxArrayString fpFilters;
|
||||||
|
fpFilters.Add( aFootprintName ); // In cadstar one footprint has several "alternates"
|
||||||
|
|
||||||
|
if( !aFootprintAlternate.IsEmpty() )
|
||||||
fpFilters.Add( fpNameInLibrary );
|
fpFilters.Add( fpNameInLibrary );
|
||||||
aSymbol->SetFPFilters( fpFilters );
|
|
||||||
|
|
||||||
// Assume that the PCB footprint library name will be the same as the schematic filename
|
aKiCadSymbol->SetFPFilters( fpFilters );
|
||||||
wxFileName schFilename( Filename );
|
|
||||||
wxString libName = schFilename.GetName();
|
|
||||||
aSymbol->GetFootprintField().SetText( libName + wxT( ":" ) + fpNameInLibrary );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( aCadstarPart->Definition.HidePinNames )
|
LIB_ID libID( m_footprintLibName, fpNameInLibrary );
|
||||||
{
|
aKiCadSymbol->GetFootprintField().SetText( libID.Format() );
|
||||||
aSymbol->SetShowPinNames( false );
|
|
||||||
aSymbol->SetShowPinNumbers( false );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
|
|
||||||
class BUS_ALIAS;
|
class BUS_ALIAS;
|
||||||
|
class CADSTAR_PART_ENTRY;
|
||||||
class EDA_TEXT;
|
class EDA_TEXT;
|
||||||
class TEXT_SPIN_STYLE;
|
class TEXT_SPIN_STYLE;
|
||||||
class LIB_FIELD;
|
class LIB_FIELD;
|
||||||
|
@ -70,6 +71,10 @@ public:
|
||||||
m_designCenter.y = 0;
|
m_designCenter.y = 0;
|
||||||
m_reporter = aReporter;
|
m_reporter = aReporter;
|
||||||
m_progressReporter = aProgressReporter;
|
m_progressReporter = aProgressReporter;
|
||||||
|
|
||||||
|
// Assume that the PCB footprint library name will be the same as the schematic filename
|
||||||
|
wxFileName schFilename( Filename );
|
||||||
|
m_footprintLibName = schFilename.GetName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,8 +82,13 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<LIB_SYMBOL*> LoadPartsLib( const wxString& aFilename );
|
||||||
|
|
||||||
const std::vector<LIB_SYMBOL*>& GetLoadedSymbols() const { return m_loadedSymbols; }
|
const std::vector<LIB_SYMBOL*>& GetLoadedSymbols() const { return m_loadedSymbols; }
|
||||||
|
|
||||||
|
void SetFpLibName( const wxString& aLibName ) { m_footprintLibName = aLibName; };
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Loads a CADSTAR Schematic Archive file into the KiCad SCHEMATIC object given
|
* @brief Loads a CADSTAR Schematic Archive file into the KiCad SCHEMATIC object given
|
||||||
* @param aSchematic Schematic to add the design onto
|
* @param aSchematic Schematic to add the design onto
|
||||||
|
@ -99,9 +109,10 @@ private:
|
||||||
|
|
||||||
typedef std::map<wxString, TERMINAL_ID> PINNUM_TO_TERMINAL_MAP;
|
typedef std::map<wxString, TERMINAL_ID> PINNUM_TO_TERMINAL_MAP;
|
||||||
|
|
||||||
REPORTER* m_reporter;
|
REPORTER* m_reporter;
|
||||||
SCHEMATIC* m_schematic;
|
SCHEMATIC* m_schematic;
|
||||||
SCH_SHEET* m_rootSheet;
|
SCH_SHEET* m_rootSheet;
|
||||||
|
wxString m_footprintLibName; ///< Name of the footprint library to prepend all footprints with
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Required for calculating the offset to apply to the Cadstar design so that it fits
|
* Required for calculating the offset to apply to the Cadstar design so that it fits
|
||||||
|
@ -141,6 +152,12 @@ private:
|
||||||
void loadDocumentationSymbols();
|
void loadDocumentationSymbols();
|
||||||
void loadTextVariables();
|
void loadTextVariables();
|
||||||
|
|
||||||
|
std::unique_ptr<LIB_SYMBOL> loadLibPart( const CADSTAR_PART_ENTRY& aPart );
|
||||||
|
|
||||||
|
void copySymbolItems( std::unique_ptr<LIB_SYMBOL>& aSourceSym,
|
||||||
|
std::unique_ptr<LIB_SYMBOL>& aDestSym, int aDestUnit,
|
||||||
|
bool aOverrideFields = true );
|
||||||
|
|
||||||
//Helper Functions for loading sheets
|
//Helper Functions for loading sheets
|
||||||
void loadSheetAndChildSheets( LAYER_ID aCadstarSheetID, const VECTOR2I& aPosition,
|
void loadSheetAndChildSheets( LAYER_ID aCadstarSheetID, const VECTOR2I& aPosition,
|
||||||
VECTOR2I aSheetSize, const SCH_SHEET_PATH& aParentSheet );
|
VECTOR2I aSheetSize, const SCH_SHEET_PATH& aParentSheet );
|
||||||
|
@ -156,9 +173,13 @@ private:
|
||||||
//Helper Functions for loading library items
|
//Helper Functions for loading library items
|
||||||
const LIB_SYMBOL* loadSymdef( const SYMDEF_ID& aSymdefID );
|
const LIB_SYMBOL* loadSymdef( const SYMDEF_ID& aSymdefID );
|
||||||
|
|
||||||
void loadSymbolGateAndPartFields( const SYMDEF_ID& aSymdefID, const PART* aCadstarPart,
|
void loadSymbolGateAndPartFields( const SYMDEF_ID& aSymdefID, const PART& aCadstarPart,
|
||||||
const GATE_ID& aGateID, LIB_SYMBOL* aSymbol );
|
const GATE_ID& aGateID, LIB_SYMBOL* aSymbol );
|
||||||
|
|
||||||
|
void setFootprintOnSymbol( std::unique_ptr<LIB_SYMBOL>& aKiCadSymbol,
|
||||||
|
const wxString& aFootprintName,
|
||||||
|
const wxString& aFootprintAlternate );
|
||||||
|
|
||||||
void loadLibrarySymbolShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
|
void loadLibrarySymbolShapeVertices( const std::vector<VERTEX>& aCadstarVertices,
|
||||||
VECTOR2I aSymbolOrigin, LIB_SYMBOL* aSymbol,
|
VECTOR2I aSymbolOrigin, LIB_SYMBOL* aSymbol,
|
||||||
int aGateNumber, int aLineThickness );
|
int aGateNumber, int aLineThickness );
|
||||||
|
@ -304,7 +325,8 @@ private:
|
||||||
double getPolarRadius( const VECTOR2I& aPoint );
|
double getPolarRadius( const VECTOR2I& aPoint );
|
||||||
|
|
||||||
|
|
||||||
static LIB_FIELD* addNewFieldToSymbol( const wxString& aFieldName, LIB_SYMBOL* aKiCadSymbol );
|
static LIB_FIELD* addNewFieldToSymbol( const wxString& aFieldName,
|
||||||
|
std::unique_ptr<LIB_SYMBOL>& aKiCadSymbol );
|
||||||
|
|
||||||
}; // CADSTAR_SCH_ARCHIVE_LOADER
|
}; // CADSTAR_SCH_ARCHIVE_LOADER
|
||||||
|
|
||||||
|
|
|
@ -197,17 +197,23 @@ void CADSTAR_SCH_ARCHIVE_PLUGIN::EnumerateSymbolLib( std::vector<LIB_SYMBOL*>& a
|
||||||
const wxString& aLibraryPath,
|
const wxString& aLibraryPath,
|
||||||
const STRING_UTF8_MAP* aProperties )
|
const STRING_UTF8_MAP* aProperties )
|
||||||
{
|
{
|
||||||
|
static std::vector<LIB_SYMBOL*> cached;
|
||||||
|
static wxString cachedPath;
|
||||||
|
|
||||||
|
if(cachedPath == aLibraryPath)
|
||||||
|
{
|
||||||
|
aSymbolList = cached;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wxFileName fn( aLibraryPath );
|
wxFileName fn( aLibraryPath );
|
||||||
fn.SetExt( "csa" );
|
fn.SetExt( "csa" );
|
||||||
fn.SetName( "symbol" );
|
fn.SetName( "symbol" );
|
||||||
|
|
||||||
CADSTAR_SCH_ARCHIVE_LOADER csaLoader( fn.GetFullPath(), m_reporter, m_progressReporter );
|
CADSTAR_SCH_ARCHIVE_LOADER csaLoader( fn.GetFullPath(), m_reporter, m_progressReporter );
|
||||||
|
aSymbolList = csaLoader.LoadPartsLib( aLibraryPath );
|
||||||
if( m_progressReporter )
|
cachedPath = aLibraryPath;
|
||||||
m_progressReporter->SetNumPhases( 2 ); // (0) Read file, (1) Parse file
|
cached = aSymbolList;
|
||||||
|
|
||||||
csaLoader.Parse();
|
|
||||||
printf( "symbols: %zd", csaLoader.Library.SymbolDefinitions.size() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -215,6 +221,15 @@ LIB_SYMBOL* CADSTAR_SCH_ARCHIVE_PLUGIN::LoadSymbol( const wxString& aLibr
|
||||||
const wxString& aAliasName,
|
const wxString& aAliasName,
|
||||||
const STRING_UTF8_MAP* aProperties )
|
const STRING_UTF8_MAP* aProperties )
|
||||||
{
|
{
|
||||||
|
std::vector<LIB_SYMBOL*> symbols;
|
||||||
|
EnumerateSymbolLib( symbols, aLibraryPath, aProperties );
|
||||||
|
|
||||||
|
for( LIB_SYMBOL*& sym : symbols )
|
||||||
|
{
|
||||||
|
if( sym->GetName() == aAliasName )
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,8 +127,7 @@ BOOST_AUTO_TEST_CASE( ReadFile )
|
||||||
BOOST_CHECK_EQUAL( partEntry.m_PinsVisible, i % 5 != 1 );
|
BOOST_CHECK_EQUAL( partEntry.m_PinsVisible, i % 5 != 1 );
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( partEntry.m_SpicePartName, "PartName" + std::to_string( i ) );
|
BOOST_CHECK_EQUAL( partEntry.m_SpicePartName, "PartName" + std::to_string( i ) );
|
||||||
BOOST_CHECK_EQUAL( partEntry.m_SpiceModel, std::optional<std::string>() );
|
BOOST_CHECK_EQUAL( partEntry.m_SpiceModel, std::to_string( i ) + "uH" );
|
||||||
BOOST_CHECK_EQUAL( partEntry.m_SpiceValue, std::to_string( i ) + "uH" );
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( partEntry.m_AcceptancePartName, "PartName" + std::to_string( i ) );
|
BOOST_CHECK_EQUAL( partEntry.m_AcceptancePartName, "PartName" + std::to_string( i ) );
|
||||||
BOOST_CHECK_EQUAL( partEntry.m_AcceptanceText, "Acceptance" + std::to_string( i ) );
|
BOOST_CHECK_EQUAL( partEntry.m_AcceptanceText, "Acceptance" + std::to_string( i ) );
|
||||||
|
@ -341,8 +340,7 @@ BOOST_AUTO_TEST_CASE( ReadContent )
|
||||||
|
|
||||||
// Check *SPI
|
// Check *SPI
|
||||||
BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_SpicePartName, "<Part name>" );
|
BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_SpicePartName, "<Part name>" );
|
||||||
BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_SpiceModel, "<Model>" );
|
BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_SpiceModel, "<Model> <Value>" );
|
||||||
BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_SpiceValue, "<Value>" );
|
|
||||||
|
|
||||||
// Check *PAC
|
// Check *PAC
|
||||||
BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_AcceptancePartName, "<Part name>" );
|
BOOST_CHECK_EQUAL( result.m_PartEntries[0].m_AcceptancePartName, "<Part name>" );
|
||||||
|
|
Loading…
Reference in New Issue