7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-21 17:03:44 +00:00

Move more properties into PADSTACK

This commit is contained in:
Jon Evans 2024-07-20 17:47:59 -04:00
parent 6ed537753c
commit 284a760af7
5 changed files with 338 additions and 106 deletions

View File

@ -183,6 +183,39 @@ message ChamferedRectCorners
bool bottom_right = 4;
}
// enum class ZONE_CONNECTION
enum ZoneConnectionStyle
{
ZCS_UNKNOWN = 0;
ZCS_INHERITED = 1;
ZCS_NONE = 2;
ZCS_THERMAL = 3;
ZCS_FULL = 4;
ZCS_PTH_THERMAL = 5; // Thermal reliefs for plated through holes, solid for SMD pads
}
message ZoneConnectionSettings
{
ZoneConnectionStyle zone_connection = 1;
ThermalSpokeSettings thermal_spokes = 2;
}
message SolderMaskOverrides
{
// Solder mask expansion/contraction
kiapi.common.types.Distance solder_mask_margin = 1;
}
message SolderPasteOverrides
{
// Solder paste expansion/contraction
kiapi.common.types.Distance solder_paste_margin = 1;
// Solder paste expansion/contraction ratio
kiapi.common.types.Ratio solder_paste_margin_ratio = 2;
}
// The defintion of a padstack on a single layer
message PadStackLayer
{
@ -209,6 +242,33 @@ message PadStackLayer
// If shape == PSS_CUSTOM, defines the shape of the anchor (only PSS_CIRCLE and PSS_RECTANGLE supported at present)
PadStackShape custom_anchor_shape = 8;
ZoneConnectionSettings zone_settings = 9;
}
enum SolderMaskMode
{
SMM_UNKOWN = 0;
SMM_MASKED = 1;
SMM_UNMASKED = 2;
SMM_FROM_DESIGN_RULES = 3;
}
enum SolderPasteMode
{
SPM_UNKOWN = 0;
SPM_PASTE = 1;
SPM_NO_PASTE = 2;
SPM_FROM_DESIGN_RULES = 3;
}
// Properties for the outer technical layers of a padstack on the top or bottom of the stack
message PadStackOuterLayer
{
SolderMaskMode solder_mask_mode = 1;
SolderPasteMode solder_paste_mode = 2;
SolderMaskOverrides solder_mask_settings = 3;
SolderPasteOverrides solder_paste_settings = 4;
}
// A pad stack definition for a multilayer pad or via.
@ -234,6 +294,12 @@ message PadStack
// The overall rotation of this padstack (affects all layers)
kiapi.common.types.Angle angle = 7;
// Solder mask and paste settings for the front
PadStackOuterLayer front_outer_layers = 8;
// Solder mask and paste settings for the back
PadStackOuterLayer back_outer_layers = 9;
}
enum ViaType
@ -378,9 +444,8 @@ message Pad
// A pad's position is always relative to the parent footprint's origin
kiapi.common.types.Vector2 position = 7;
DesignRuleOverrides overrides = 8;
ThermalSpokeSettings thermal_spokes = 9;
// Copper-to-copper clearance override
kiapi.common.types.Distance copper_clearance_override = 8;
}
// Copper zone, non-copper zone, or rule area
@ -443,46 +508,26 @@ message FootprintAttributes
FootprintMountingStyle mounting_style = 8;
}
// enum class ZONE_CONNECTION
enum ZoneConnectionStyle
{
ZCS_UNKNOWN = 0;
ZCS_INHERITED = 1;
ZCS_NONE = 2;
ZCS_THERMAL = 3;
ZCS_FULL = 4;
ZCS_PTH_THERMAL = 5; // Thermal reliefs for plated through holes, solid for SMD pads
}
message DesignRuleOverrides
{
// Copper-to-copper clearance override
kiapi.common.types.Distance clearance = 1;
// Solder mask expansion/contraction
kiapi.common.types.Distance solder_mask_margin = 2;
// Solder paste expansion/contraction
kiapi.common.types.Distance solder_paste_margin = 3;
// Solder paste expansion/contraction ratio
kiapi.common.types.Ratio solder_paste_margin_ratio = 4;
ZoneConnectionStyle zone_connection = 5;
}
message NetTieDefinition
{
repeated string pad_number = 1;
}
message FootprintDesignRuleOverrides
{
SolderMaskOverrides solder_mask = 1;
SolderPasteOverrides solder_paste = 2;
kiapi.common.types.Distance copper_clearance = 3;
ZoneConnectionStyle zone_connection = 4;
}
// A footprint definition (i.e. what would be in a library)
message Footprint
{
kiapi.common.types.LibraryIdentifier id = 1;
kiapi.common.types.Vector2 anchor = 2;
FootprintAttributes attributes = 3;
DesignRuleOverrides overrides = 4;
FootprintDesignRuleOverrides overrides = 4;
repeated NetTieDefinition net_ties = 5;
repeated BoardLayer private_layers = 6;
@ -511,5 +556,5 @@ message FootprintInstance
Field description_field = 10;
FootprintAttributes attributes = 11;
DesignRuleOverrides overrides = 12;
FootprintDesignRuleOverrides overrides = 12;
}

View File

@ -308,19 +308,19 @@ void FOOTPRINT::Serialize( google::protobuf::Any &aContainer ) const
// TODO: serialize library mandatory fields
kiapi::board::types::DesignRuleOverrides* overrides = def->mutable_overrides();
kiapi::board::types::FootprintDesignRuleOverrides* overrides = def->mutable_overrides();
if( GetLocalClearance().has_value() )
overrides->mutable_clearance()->set_value_nm( *GetLocalClearance() );
overrides->mutable_copper_clearance()->set_value_nm( *GetLocalClearance() );
if( GetLocalSolderMaskMargin().has_value() )
overrides->mutable_solder_mask_margin()->set_value_nm( *GetLocalSolderMaskMargin() );
overrides->mutable_solder_mask()->mutable_solder_mask_margin()->set_value_nm( *GetLocalSolderMaskMargin() );
if( GetLocalSolderPasteMargin().has_value() )
overrides->mutable_solder_paste_margin()->set_value_nm( *GetLocalSolderPasteMargin() );
overrides->mutable_solder_paste()->mutable_solder_paste_margin()->set_value_nm( *GetLocalSolderPasteMargin() );
if( GetLocalSolderPasteMarginRatio().has_value() )
overrides->mutable_solder_paste_margin_ratio()->set_value( *GetLocalSolderPasteMarginRatio() );
overrides->mutable_solder_paste()->mutable_solder_paste_margin_ratio()->set_value( *GetLocalSolderPasteMarginRatio() );
overrides->set_zone_connection(
ToProtoEnum<ZONE_CONNECTION,
@ -434,27 +434,32 @@ bool FOOTPRINT::Deserialize( const google::protobuf::Any &aContainer )
SetLibDescription( footprint.definition().attributes().description() );
SetKeywords( footprint.definition().attributes().keywords() );
const kiapi::board::types::DesignRuleOverrides& overrides = footprint.overrides();
const kiapi::board::types::FootprintDesignRuleOverrides& overrides = footprint.overrides();
if( overrides.has_clearance() )
SetLocalClearance( overrides.clearance().value_nm() );
if( overrides.has_copper_clearance() )
SetLocalClearance( overrides.copper_clearance().value_nm() );
else
SetLocalClearance( std::nullopt );
if( overrides.has_solder_mask_margin() )
SetLocalSolderMaskMargin( overrides.solder_mask_margin().value_nm() );
if( overrides.has_solder_mask() && overrides.solder_mask().has_solder_mask_margin() )
SetLocalSolderMaskMargin( overrides.solder_mask().solder_mask_margin().value_nm() );
else
SetLocalSolderMaskMargin( std::nullopt );
if( overrides.has_solder_paste_margin() )
SetLocalSolderPasteMargin( overrides.solder_paste_margin().value_nm() );
else
SetLocalSolderPasteMargin( std::nullopt );
if( overrides.has_solder_paste() )
{
const kiapi::board::types::SolderPasteOverrides& pasteSettings = overrides.solder_paste();
if( overrides.has_solder_paste_margin_ratio() )
SetLocalSolderPasteMarginRatio( overrides.solder_paste_margin_ratio().value() );
else
SetLocalSolderPasteMarginRatio( std::nullopt );
if( pasteSettings.has_solder_paste_margin() )
SetLocalSolderPasteMargin( pasteSettings.solder_paste_margin().value_nm() );
else
SetLocalSolderPasteMargin( std::nullopt );
if( pasteSettings.has_solder_paste_margin_ratio() )
SetLocalSolderPasteMarginRatio( pasteSettings.solder_paste_margin_ratio().value() );
else
SetLocalSolderPasteMarginRatio( std::nullopt );
}
SetLocalZoneConnection( FromProtoEnum<ZONE_CONNECTION>( overrides.zone_connection() ) );

View File

@ -150,28 +150,8 @@ void PAD::Serialize( google::protobuf::Any &aContainer ) const
m_padStack.Serialize( padStackMsg );
padStackMsg.UnpackTo( pad.mutable_pad_stack() );
DesignRuleOverrides* overrides = pad.mutable_overrides();
if( GetLocalClearance().has_value() )
overrides->mutable_clearance()->set_value_nm( *GetLocalClearance() );
if( GetLocalSolderMaskMargin().has_value() )
overrides->mutable_solder_mask_margin()->set_value_nm( *GetLocalSolderMaskMargin() );
if( GetLocalSolderPasteMargin().has_value() )
overrides->mutable_solder_paste_margin()->set_value_nm( *GetLocalSolderPasteMargin() );
if( GetLocalSolderPasteMarginRatio().has_value() )
overrides->mutable_solder_paste_margin_ratio()->set_value( *GetLocalSolderPasteMarginRatio() );
overrides->set_zone_connection(
ToProtoEnum<ZONE_CONNECTION, ZoneConnectionStyle>( GetLocalZoneConnection() ) );
ThermalSpokeSettings* thermals = pad.mutable_thermal_spokes();
thermals->set_width( GetThermalSpokeWidth() );
thermals->set_gap( GetThermalGap() );
thermals->mutable_angle()->set_value_degrees( GetThermalSpokeAngleDegrees() );
pad.mutable_copper_clearance_override()->set_value_nm( *GetLocalClearance() );
aContainer.PackFrom( pad );
}
@ -196,36 +176,11 @@ bool PAD::Deserialize( const google::protobuf::Any &aContainer )
SetLayer( m_padStack.StartLayer() );
const kiapi::board::types::DesignRuleOverrides& overrides = pad.overrides();
if( overrides.has_clearance() )
SetLocalClearance( overrides.clearance().value_nm() );
if( pad.has_copper_clearance_override() )
SetLocalClearance( pad.copper_clearance_override().value_nm() );
else
SetLocalClearance( std::nullopt );
if( overrides.has_solder_mask_margin() )
SetLocalSolderMaskMargin( overrides.solder_mask_margin().value_nm() );
else
SetLocalSolderMaskMargin( std::nullopt );
if( overrides.has_solder_paste_margin() )
SetLocalSolderPasteMargin( overrides.solder_paste_margin().value_nm() );
else
SetLocalSolderPasteMargin( std::nullopt );
if( overrides.has_solder_paste_margin_ratio() )
SetLocalSolderPasteMarginRatio( overrides.solder_paste_margin_ratio().value() );
else
SetLocalSolderPasteMarginRatio( std::nullopt );
SetLocalZoneConnection( FromProtoEnum<ZONE_CONNECTION>( overrides.zone_connection() ) );
const kiapi::board::types::ThermalSpokeSettings& thermals = pad.thermal_spokes();
SetThermalGap( thermals.gap() );
SetThermalSpokeWidth( thermals.width() );
SetThermalSpokeAngleDegrees( thermals.angle().value_degrees() );
return true;
}

View File

@ -36,9 +36,9 @@ PADSTACK::PADSTACK( BOARD_ITEM* aParent ) :
{
m_defaultCopperProps.shape = SHAPE_PROPS();
m_defaultCopperProps.zone_connection = ZONE_CONNECTION::INHERITED;
m_defaultCopperProps.thermal_spoke_width = std::nullopt;
m_defaultCopperProps.thermal_spoke_width = 0;
m_defaultCopperProps.thermal_spoke_angle = ANGLE_45;
m_defaultCopperProps.thermal_gap = std::nullopt;
m_defaultCopperProps.thermal_gap = 0;
m_drill.shape = PAD_DRILL_SHAPE::CIRCLE;
m_drill.start = F_Cu;
@ -141,11 +141,152 @@ bool PADSTACK::Deserialize( const google::protobuf::Any& aContainer )
if( shape->Deserialize( a ) )
AddPrimitive( shape.release() );
}
if( layer.has_zone_settings() )
{
CopperLayerDefaults().zone_connection =
FromProtoEnum<ZONE_CONNECTION>( layer.zone_settings().zone_connection() );
if( layer.zone_settings().has_thermal_spokes() )
{
const ThermalSpokeSettings& thermals = layer.zone_settings().thermal_spokes();
CopperLayerDefaults().thermal_gap = thermals.gap();
CopperLayerDefaults().thermal_spoke_width = thermals.width();
SetThermalSpokeAngle( thermals.angle().value_degrees() );
}
}
else
{
CopperLayerDefaults().zone_connection = ZONE_CONNECTION::INHERITED;
CopperLayerDefaults().thermal_gap = 0;
CopperLayerDefaults().thermal_spoke_width = 0;
CopperLayerDefaults().thermal_spoke_angle = DefaultThermalSpokeAngleForShape();
}
}
SetUnconnectedLayerMode(
FromProtoEnum<UNCONNECTED_LAYER_MODE>( padstack.unconnected_layer_removal() ) );
auto unpackMask =
[]( const SolderMaskMode& aProto, std::optional<bool>& aDest )
{
switch( aProto )
{
case kiapi::board::types::SMM_MASKED:
aDest = true;
break;
case kiapi::board::types::SMM_UNMASKED:
aDest = false;
break;
default:
case kiapi::board::types::SMM_FROM_DESIGN_RULES:
aDest = std::nullopt;
break;
}
};
unpackMask( padstack.front_outer_layers().solder_mask_mode(),
FrontOuterLayers().has_solder_mask );
unpackMask( padstack.back_outer_layers().solder_mask_mode(),
BackOuterLayers().has_solder_mask );
auto unpackPaste =
[]( const SolderPasteMode& aProto, std::optional<bool>& aDest )
{
switch( aProto )
{
case kiapi::board::types::SPM_PASTE:
aDest = true;
break;
case kiapi::board::types::SPM_NO_PASTE:
aDest = false;
break;
default:
case kiapi::board::types::SPM_FROM_DESIGN_RULES:
aDest = std::nullopt;
break;
}
};
unpackPaste( padstack.front_outer_layers().solder_paste_mode(),
FrontOuterLayers().has_solder_paste );
unpackPaste( padstack.back_outer_layers().solder_paste_mode(),
BackOuterLayers().has_solder_paste );
if( padstack.front_outer_layers().has_solder_mask_settings()
&& padstack.front_outer_layers().solder_mask_settings().has_solder_mask_margin() )
{
FrontOuterLayers().solder_mask_margin =
padstack.front_outer_layers().solder_mask_settings().solder_mask_margin().value_nm();
}
else
{
FrontOuterLayers().solder_mask_margin = std::nullopt;
}
if( padstack.back_outer_layers().has_solder_mask_settings()
&& padstack.back_outer_layers().solder_mask_settings().has_solder_mask_margin() )
{
BackOuterLayers().solder_mask_margin =
padstack.back_outer_layers().solder_mask_settings().solder_mask_margin().value_nm();
}
else
{
BackOuterLayers().solder_mask_margin = std::nullopt;
}
if( padstack.front_outer_layers().has_solder_paste_settings()
&& padstack.front_outer_layers().solder_paste_settings().has_solder_paste_margin() )
{
FrontOuterLayers().solder_paste_margin =
padstack.front_outer_layers().solder_paste_settings().solder_paste_margin().value_nm();
}
else
{
FrontOuterLayers().solder_paste_margin = std::nullopt;
}
if( padstack.back_outer_layers().has_solder_paste_settings()
&& padstack.back_outer_layers().solder_paste_settings().has_solder_paste_margin() )
{
BackOuterLayers().solder_paste_margin =
padstack.back_outer_layers().solder_paste_settings().solder_paste_margin().value_nm();
}
else
{
BackOuterLayers().solder_paste_margin = std::nullopt;
}
if( padstack.front_outer_layers().has_solder_paste_settings()
&& padstack.front_outer_layers().solder_paste_settings().has_solder_paste_margin_ratio() )
{
FrontOuterLayers().solder_paste_margin_ratio =
padstack.front_outer_layers().solder_paste_settings().solder_paste_margin_ratio().value();
}
else
{
FrontOuterLayers().solder_paste_margin_ratio = std::nullopt;
}
if( padstack.back_outer_layers().has_solder_paste_settings()
&& padstack.back_outer_layers().solder_paste_settings().has_solder_paste_margin_ratio() )
{
BackOuterLayers().solder_paste_margin_ratio =
padstack.back_outer_layers().solder_paste_settings().solder_paste_margin_ratio().value();
}
else
{
BackOuterLayers().solder_paste_margin_ratio = std::nullopt;
}
return true;
}
@ -184,9 +325,87 @@ void PADSTACK::Serialize( google::protobuf::Any& aContainer ) const
stackLayer->mutable_chamfered_corners()->set_bottom_left( corners & RECT_CHAMFER_BOTTOM_LEFT );
stackLayer->mutable_chamfered_corners()->set_bottom_right( corners & RECT_CHAMFER_BOTTOM_RIGHT );
ZoneConnectionSettings* zoneSettings = stackLayer->mutable_zone_settings();
ThermalSpokeSettings* thermalSettings = zoneSettings->mutable_thermal_spokes();
if( CopperLayerDefaults().zone_connection.has_value() )
{
zoneSettings->set_zone_connection( ToProtoEnum<ZONE_CONNECTION, ZoneConnectionStyle>(
*CopperLayerDefaults().zone_connection ) );
}
thermalSettings->set_width( CopperLayerDefaults().thermal_spoke_width.value_or( 0 ) );
thermalSettings->set_gap( CopperLayerDefaults().thermal_gap.value_or( 0 ) );
thermalSettings->mutable_angle()->set_value_degrees( ThermalSpokeAngle().AsDegrees() );
padstack.set_unconnected_layer_removal(
ToProtoEnum<UNCONNECTED_LAYER_MODE, UnconnectedLayerRemoval>( m_unconnectedLayerMode ) );
auto packOptional =
[]<typename ProtoEnum>( const std::optional<bool>& aVal, ProtoEnum aTrueVal,
ProtoEnum aFalseVal, ProtoEnum aNullVal ) -> ProtoEnum
{
if( aVal.has_value() )
return *aVal ? aTrueVal : aFalseVal;
return aNullVal;
};
PadStackOuterLayer* frontOuter = padstack.mutable_front_outer_layers();
PadStackOuterLayer* backOuter = padstack.mutable_back_outer_layers();
frontOuter->set_solder_mask_mode( packOptional( FrontOuterLayers().has_solder_mask,
SMM_MASKED, SMM_UNMASKED,
SMM_FROM_DESIGN_RULES ) );
backOuter->set_solder_mask_mode( packOptional( BackOuterLayers().has_solder_mask,
SMM_MASKED, SMM_UNMASKED,
SMM_FROM_DESIGN_RULES ) );
frontOuter->set_solder_paste_mode( packOptional( FrontOuterLayers().has_solder_paste,
SPM_PASTE, SPM_NO_PASTE,
SPM_FROM_DESIGN_RULES ) );
backOuter->set_solder_paste_mode( packOptional( BackOuterLayers().has_solder_paste,
SPM_PASTE, SPM_NO_PASTE,
SPM_FROM_DESIGN_RULES ) );
if( FrontOuterLayers().solder_mask_margin.has_value() )
{
frontOuter->mutable_solder_mask_settings()->mutable_solder_mask_margin()->set_value_nm(
*FrontOuterLayers().solder_mask_margin );
}
if( BackOuterLayers().solder_mask_margin.has_value() )
{
backOuter->mutable_solder_mask_settings()->mutable_solder_mask_margin()->set_value_nm(
*BackOuterLayers().solder_mask_margin );
}
if( FrontOuterLayers().solder_paste_margin.has_value() )
{
frontOuter->mutable_solder_paste_settings()->mutable_solder_paste_margin()->set_value_nm(
*FrontOuterLayers().solder_paste_margin );
}
if( BackOuterLayers().solder_paste_margin.has_value() )
{
backOuter->mutable_solder_paste_settings()->mutable_solder_paste_margin()->set_value_nm(
*BackOuterLayers().solder_paste_margin );
}
if( FrontOuterLayers().solder_paste_margin_ratio.has_value() )
{
frontOuter->mutable_solder_paste_settings()->mutable_solder_paste_margin_ratio()->set_value(
*FrontOuterLayers().solder_paste_margin_ratio );
}
if( BackOuterLayers().solder_paste_margin_ratio.has_value() )
{
backOuter->mutable_solder_paste_settings()->mutable_solder_paste_margin_ratio()->set_value(
*BackOuterLayers().solder_paste_margin_ratio );
}
aContainer.PackFrom( padstack );
}
@ -477,15 +696,22 @@ const std::optional<int>& PADSTACK::ThermalGap( PCB_LAYER_ID aLayer ) const
}
EDA_ANGLE PADSTACK::DefaultThermalSpokeAngleForShape( PCB_LAYER_ID aLayer ) const
{
const COPPER_LAYER_PROPS& defaults = CopperLayerDefaults();
return ( defaults.shape.shape == PAD_SHAPE::CIRCLE
|| ( defaults.shape.shape == PAD_SHAPE::CUSTOM
&& defaults.shape.anchor_shape == PAD_SHAPE::CIRCLE ) )
? ANGLE_45 : ANGLE_90;
}
EDA_ANGLE PADSTACK::ThermalSpokeAngle( PCB_LAYER_ID aLayer ) const
{
const COPPER_LAYER_PROPS& defaults = CopperLayerDefaults();
return defaults.thermal_spoke_angle.value_or(
( defaults.shape.shape == PAD_SHAPE::CIRCLE
|| ( defaults.shape.shape == PAD_SHAPE::CUSTOM
&& defaults.shape.anchor_shape == PAD_SHAPE::CIRCLE ) )
? ANGLE_45 : ANGLE_90 );
return defaults.thermal_spoke_angle.value_or( DefaultThermalSpokeAngleForShape( aLayer ) );
}

View File

@ -346,6 +346,7 @@ public:
std::optional<int>& ThermalGap( PCB_LAYER_ID aLayer = F_Cu );
const std::optional<int>& ThermalGap( PCB_LAYER_ID aLayer = F_Cu ) const;
EDA_ANGLE DefaultThermalSpokeAngleForShape( PCB_LAYER_ID aLayer = F_Cu ) const;
EDA_ANGLE ThermalSpokeAngle( PCB_LAYER_ID aLayer = F_Cu ) const;
void SetThermalSpokeAngle( EDA_ANGLE aAngle, PCB_LAYER_ID aLayer = F_Cu );