CADSTAR PCB Archive Importer: Load correct pad information for pads with PADEXCEPTION

Overwrites pad definitions for pads that have PADEXCEPTION
This commit is contained in:
Roberto Fernandez Bautista 2020-10-24 18:02:44 +01:00 committed by Wayne Stambaugh
parent 7a1777e9b9
commit 0dc153fe58
2 changed files with 185 additions and 144 deletions

View File

@ -681,157 +681,165 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadLibraryPads( const SYMDEF_PCB& aComponent,
{
for( std::pair<PAD_ID, PAD> padPair : aComponent.Pads )
{
PAD& csPad = padPair.second; //Cadstar pad
PADCODE csPadcode = getPadCode( csPad.PadCodeID );
D_PAD* pad = new D_PAD( aModule );
D_PAD* pad = getKiCadPad( padPair.second, aModule );
aModule->Add( pad,
ADD_MODE::INSERT ); // insert so that we get correct behaviour when finding pads
// in the module by PAD_ID - see loadNets()
switch( csPad.Side )
{
case PAD_SIDE::MAXIMUM: //Bottom side
pad->SetAttribute( PAD_ATTR_T::PAD_ATTRIB_SMD );
pad->SetLayerSet( LSET( 3, B_Cu, B_Paste, B_Mask ) );
break;
case PAD_SIDE::MINIMUM: //TOP side
pad->SetAttribute( PAD_ATTR_T::PAD_ATTRIB_SMD );
pad->SetLayerSet( LSET( 3, F_Cu, F_Paste, F_Mask ) );
break;
case PAD_SIDE::THROUGH_HOLE:
if( csPadcode.Plated )
pad->SetAttribute( PAD_ATTR_T::PAD_ATTRIB_PTH );
else
pad->SetAttribute( PAD_ATTR_T::PAD_ATTRIB_NPTH );
pad->SetLayerSet( pad->PTHMask() ); // for now we will assume no paste layers
//TODO: We need to read the csPad->Reassigns vector to make sure no paste
break;
default:
wxFAIL_MSG( "Unknown Pad type" );
}
pad->SetName( csPad.Identifier.IsEmpty() ? wxString::Format( wxT( "%ld" ), csPad.ID ) :
csPad.Identifier );
pad->SetPos0( getKiCadPoint( csPad.Position ) - aModule->GetPosition() );
pad->SetOrientation( getAngleTenthDegree( csPad.OrientAngle ) );
if( csPadcode.Shape.Size == 0 )
// zero sized pads seems to break KiCad so lets make it very small instead
csPadcode.Shape.Size = 1;
switch( csPadcode.Shape.ShapeType )
{
case PAD_SHAPE_TYPE::ANNULUS:
//todo fix: use custom shape instead (Donught shape, i.e. a circle with a hole)
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_CIRCLE );
pad->SetSize( { getKiCadLength( csPadcode.Shape.Size ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::BULLET:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_CHAMFERED_RECT );
pad->SetSize( { getKiCadLength( (long long) csPadcode.Shape.Size
+ (long long) csPadcode.Shape.LeftLength
+ (long long) csPadcode.Shape.RightLength ),
getKiCadLength( csPadcode.Shape.Size ) } );
pad->SetChamferPositions( RECT_CHAMFER_POSITIONS::RECT_CHAMFER_BOTTOM_LEFT
| RECT_CHAMFER_POSITIONS::RECT_CHAMFER_TOP_LEFT );
pad->SetRoundRectRadiusRatio( 0.5 );
pad->SetChamferRectRatio( 0.0 );
break;
case PAD_SHAPE_TYPE::CIRCLE:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_CIRCLE );
pad->SetSize( { getKiCadLength( csPadcode.Shape.Size ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::DIAMOND:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_RECT );
pad->SetOrientation( pad->GetOrientation() + 450.0 ); // rotate 45deg anticlockwise
pad->SetSize( { getKiCadLength( csPadcode.Shape.Size ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::FINGER:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_OVAL );
pad->SetSize( { getKiCadLength( (long long) csPadcode.Shape.Size
+ (long long) csPadcode.Shape.LeftLength
+ (long long) csPadcode.Shape.RightLength ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::OCTAGON:
pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
pad->SetChamferPositions( RECT_CHAMFER_POSITIONS::RECT_CHAMFER_ALL );
pad->SetChamferRectRatio( 0.25 );
pad->SetSize( { getKiCadLength( csPadcode.Shape.Size ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::RECTANGLE:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_RECT );
pad->SetSize( { getKiCadLength( (long long) csPadcode.Shape.Size
+ (long long) csPadcode.Shape.LeftLength
+ (long long) csPadcode.Shape.RightLength ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::ROUNDED_RECT:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_RECT );
pad->SetRoundRectCornerRadius( getKiCadLength( csPadcode.Shape.InternalFeature ) );
pad->SetSize( { getKiCadLength( (long long) csPadcode.Shape.Size
+ (long long) csPadcode.Shape.LeftLength
+ (long long) csPadcode.Shape.RightLength ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::SQUARE:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_RECT );
pad->SetSize( { getKiCadLength( csPadcode.Shape.Size ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
default:
wxFAIL_MSG( "Unknown Pad Shape" );
}
if( csPadcode.ReliefClearance != UNDEFINED_VALUE )
pad->SetThermalGap( getKiCadLength( csPadcode.ReliefClearance ) );
if( csPadcode.ReliefWidth != UNDEFINED_VALUE )
pad->SetThermalSpokeWidth( getKiCadLength( csPadcode.ReliefWidth ) );
pad->SetOrientation(
pad->GetOrientation() + getAngleTenthDegree( csPadcode.Shape.OrientAngle ) );
if( csPadcode.DrillDiameter != UNDEFINED_VALUE )
{
if( csPadcode.SlotLength != UNDEFINED_VALUE )
{
pad->SetDrillSize( { getKiCadLength( csPadcode.DrillDiameter ),
getKiCadLength( (long long) csPadcode.DrillOversize
+ (long long) csPadcode.DrillDiameter ) } );
}
else
{
pad->SetDrillSize( { getKiCadLength( csPadcode.DrillDiameter ),
getKiCadLength( csPadcode.DrillDiameter ) } );
}
}
//TODO handle csPadcode.Reassigns when KiCad supports full padstacks
}
}
D_PAD* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadPad( const PAD& aCadstarPad, MODULE* aParent )
{
PADCODE csPadcode = getPadCode( aCadstarPad.PadCodeID );
D_PAD* pad = new D_PAD( aParent );
switch( aCadstarPad.Side )
{
case PAD_SIDE::MAXIMUM: //Bottom side
pad->SetAttribute( PAD_ATTR_T::PAD_ATTRIB_SMD );
pad->SetLayerSet( LSET( 3, B_Cu, B_Paste, B_Mask ) );
break;
case PAD_SIDE::MINIMUM: //TOP side
pad->SetAttribute( PAD_ATTR_T::PAD_ATTRIB_SMD );
pad->SetLayerSet( LSET( 3, F_Cu, F_Paste, F_Mask ) );
break;
case PAD_SIDE::THROUGH_HOLE:
if( csPadcode.Plated )
pad->SetAttribute( PAD_ATTR_T::PAD_ATTRIB_PTH );
else
pad->SetAttribute( PAD_ATTR_T::PAD_ATTRIB_NPTH );
pad->SetLayerSet( pad->PTHMask() ); // for now we will assume no paste layers
//TODO: We need to read the csPad->Reassigns vector to make sure no paste
break;
default:
wxFAIL_MSG( "Unknown Pad type" );
}
pad->SetName( aCadstarPad.Identifier.IsEmpty() ?
wxString::Format( wxT( "%ld" ), aCadstarPad.ID ) :
aCadstarPad.Identifier );
pad->SetPos0( getKiCadPoint( aCadstarPad.Position ) - aParent->GetPosition() );
pad->SetOrientation( getAngleTenthDegree( aCadstarPad.OrientAngle ) );
if( csPadcode.Shape.Size == 0 )
// zero sized pads seems to break KiCad so lets make it very small instead
csPadcode.Shape.Size = 1;
switch( csPadcode.Shape.ShapeType )
{
case PAD_SHAPE_TYPE::ANNULUS:
//todo fix: use custom shape instead (Donught shape, i.e. a circle with a hole)
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_CIRCLE );
pad->SetSize( { getKiCadLength( csPadcode.Shape.Size ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::BULLET:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_CHAMFERED_RECT );
pad->SetSize( { getKiCadLength( (long long) csPadcode.Shape.Size
+ (long long) csPadcode.Shape.LeftLength
+ (long long) csPadcode.Shape.RightLength ),
getKiCadLength( csPadcode.Shape.Size ) } );
pad->SetChamferPositions( RECT_CHAMFER_POSITIONS::RECT_CHAMFER_BOTTOM_LEFT
| RECT_CHAMFER_POSITIONS::RECT_CHAMFER_TOP_LEFT );
pad->SetRoundRectRadiusRatio( 0.5 );
pad->SetChamferRectRatio( 0.0 );
break;
case PAD_SHAPE_TYPE::CIRCLE:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_CIRCLE );
pad->SetSize( { getKiCadLength( csPadcode.Shape.Size ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::DIAMOND:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_RECT );
pad->SetOrientation( pad->GetOrientation() + 450.0 ); // rotate 45deg anticlockwise
pad->SetSize( { getKiCadLength( csPadcode.Shape.Size ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::FINGER:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_OVAL );
pad->SetSize( { getKiCadLength( (long long) csPadcode.Shape.Size
+ (long long) csPadcode.Shape.LeftLength
+ (long long) csPadcode.Shape.RightLength ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::OCTAGON:
pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
pad->SetChamferPositions( RECT_CHAMFER_POSITIONS::RECT_CHAMFER_ALL );
pad->SetChamferRectRatio( 0.25 );
pad->SetSize( { getKiCadLength( csPadcode.Shape.Size ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::RECTANGLE:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_RECT );
pad->SetSize( { getKiCadLength( (long long) csPadcode.Shape.Size
+ (long long) csPadcode.Shape.LeftLength
+ (long long) csPadcode.Shape.RightLength ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::ROUNDED_RECT:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_RECT );
pad->SetRoundRectCornerRadius( getKiCadLength( csPadcode.Shape.InternalFeature ) );
pad->SetSize( { getKiCadLength( (long long) csPadcode.Shape.Size
+ (long long) csPadcode.Shape.LeftLength
+ (long long) csPadcode.Shape.RightLength ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
case PAD_SHAPE_TYPE::SQUARE:
pad->SetShape( PAD_SHAPE_T::PAD_SHAPE_RECT );
pad->SetSize( { getKiCadLength( csPadcode.Shape.Size ),
getKiCadLength( csPadcode.Shape.Size ) } );
break;
default:
wxFAIL_MSG( "Unknown Pad Shape" );
}
if( csPadcode.ReliefClearance != UNDEFINED_VALUE )
pad->SetThermalGap( getKiCadLength( csPadcode.ReliefClearance ) );
if( csPadcode.ReliefWidth != UNDEFINED_VALUE )
pad->SetThermalSpokeWidth( getKiCadLength( csPadcode.ReliefWidth ) );
pad->SetOrientation(
pad->GetOrientation() + getAngleTenthDegree( csPadcode.Shape.OrientAngle ) );
if( csPadcode.DrillDiameter != UNDEFINED_VALUE )
{
if( csPadcode.SlotLength != UNDEFINED_VALUE )
{
pad->SetDrillSize( { getKiCadLength( csPadcode.DrillDiameter ),
getKiCadLength( (long long) csPadcode.DrillOversize
+ (long long) csPadcode.DrillDiameter ) } );
}
else
{
pad->SetDrillSize( { getKiCadLength( csPadcode.DrillDiameter ),
getKiCadLength( csPadcode.DrillDiameter ) } );
}
}
//TODO handle csPadcode.Reassigns when KiCad supports full padstacks
return pad;
}
void CADSTAR_PCB_ARCHIVE_LOADER::loadGroups()
{
for( std::pair<GROUP_ID, GROUP> groupPair : Layout.Groups )
@ -1075,6 +1083,38 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadComponents()
mBoard->Add( m, ADD_MODE::APPEND );
//Override pads with pad exceptions
if( comp.PadExceptions.size() > 0 )
{
SYMDEF_PCB fpLibEntry = Library.ComponentDefinitions.at( comp.SymdefID );
for( std::pair<PAD_ID, PADEXCEPTION> padPair : comp.PadExceptions )
{
PADEXCEPTION& padEx = padPair.second;
PAD csPad = fpLibEntry.Pads.at( padPair.first );
if( !padEx.PadCode.IsEmpty() )
csPad.PadCodeID = padEx.PadCode;
if( padEx.OverrideExits )
csPad.Exits = padEx.Exits;
if( padEx.OverrideOrientation )
csPad.OrientAngle = padEx.OrientAngle;
if( padEx.OverrideSide )
csPad.Side = padEx.Side;
//Find the pad in the module definition
D_PAD* kiPad = m->Pads().at( padEx.ID - (long) 1 );
if( kiPad )
delete kiPad;
m->Pads().at( padEx.ID - (long) 1 ) = getKiCadPad( csPad, m );
}
}
//set to empty string to avoid duplication when loading attributes:
m->SetValue( wxEmptyString );

View File

@ -336,6 +336,7 @@ private:
// Helper Functions for obtaining individual elements as KiCad elements:
double getHatchCodeAngleDegrees( const HATCHCODE_ID& aCadstarHatchcodeID );
D_PAD* getKiCadPad( const PAD& aCadstarPad, MODULE* aParent );
MODULE* getModuleFromCadstarID( const COMPONENT_ID& aCadstarComponentID );
int getKiCadHatchCodeThickness( const HATCHCODE_ID& aCadstarHatchcodeID );
int getKiCadHatchCodeGap( const HATCHCODE_ID& aCadstarHatchcodeID );