Move padstack serialization to PADSTACK

Also move a few more things from pad/via
This commit is contained in:
Jon Evans 2024-06-01 16:31:50 -04:00
parent 4f4311ba57
commit 0b0a37aaf7
11 changed files with 1465 additions and 134 deletions

View File

@ -132,11 +132,19 @@ message Arc
Net net = 8; Net net = 8;
} }
// What copper layer shape mode the padstack uses
enum PadStackType enum PadStackType
{ {
PST_UNKNOWN = 0; PST_UNKNOWN = 0;
PST_THROUGH = 1; // Through all layers; same shape on all layers
PST_BLIND_BURIED = 2; // From a start layer to end layer (inclusive); same shape on all included layers // The same shape is used on all copper layers
PST_NORMAL = 1;
// The padstack uses up to three different shapes (F_Cu, inner layers, B_Cu)
PST_TOP_INNER_BOTTOM = 2;
// The padstack's shape may differ on arbitrary copper layers
PST_CUSTOM = 3;
} }
enum UnconnectedLayerRemoval enum UnconnectedLayerRemoval
@ -189,11 +197,11 @@ message PadStackLayer
// How much to round the corners of the shape by, as a fraction of min(size.x, size.y) // How much to round the corners of the shape by, as a fraction of min(size.x, size.y)
// Only used for PSS_ROUNDRECT or PSS_CHAMFEREDRECT // Only used for PSS_ROUNDRECT or PSS_CHAMFEREDRECT
float corner_rounding_ratio = 4; double corner_rounding_ratio = 4;
// How much to round the corners of the shape by, as a fraction of min(size.x, size.y) // How much to round the corners of the shape by, as a fraction of min(size.x, size.y)
// Only used for PSS_CHAMFEREDRECT // Only used for PSS_CHAMFEREDRECT
float chamfer_ratio = 5; double chamfer_ratio = 5;
ChamferedRectCorners chamfered_corners = 6; ChamferedRectCorners chamfered_corners = 6;
@ -225,6 +233,21 @@ message PadStack
kiapi.common.types.Angle angle = 7; kiapi.common.types.Angle angle = 7;
} }
enum ViaType
{
VT_UNKNOWN = 0;
// Through vias always start on F_Cu and end on B_Cu
VT_THROUGH = 1;
// Blind/buried vias can have arbitrary start and end layers
VT_BLIND_BURIED = 2;
// Microvias, blind/buried vias, can have arbitrary start and end layers, but also have different
// size defaults and design rules
VT_MICRO = 3;
}
// Represents a via // Represents a via
message Via message Via
{ {
@ -234,12 +257,14 @@ message Via
// The location of the via's center point // The location of the via's center point
kiapi.common.types.Vector2 position = 2; kiapi.common.types.Vector2 position = 2;
// The pad stack definition for this via. The via's VIATYPE (blind/buried/normal) is inferred from this. // The pad stack definition for this via.
PadStack pad_stack = 3; PadStack pad_stack = 3;
kiapi.common.types.LockedState locked = 4; kiapi.common.types.LockedState locked = 4;
Net net = 5; Net net = 5;
ViaType type = 6;
} }
message GraphicSegmentAttributes message GraphicSegmentAttributes

View File

@ -24,10 +24,44 @@
#include <wx/wx.h> #include <wx/wx.h>
#include <padstack.h> #include <padstack.h>
#include <pcb_track.h>
#include <zones.h> #include <zones.h>
using namespace kiapi::board; using namespace kiapi::board;
template<>
types::PadType ToProtoEnum( PAD_ATTRIB aValue )
{
switch( aValue )
{
case PAD_ATTRIB::PTH: return types::PadType::PT_PTH;
case PAD_ATTRIB::SMD: return types::PadType::PT_SMD;
case PAD_ATTRIB::CONN: return types::PadType::PT_EDGE_CONNECTOR;
case PAD_ATTRIB::NPTH: return types::PadType::PT_NPTH;
default:
wxCHECK_MSG( false, types::PadType::PT_UNKNOWN,
"Unhandled case in ToProtoEnum<PAD_ATTRIB>");
}
}
template<>
PAD_ATTRIB FromProtoEnum( types::PadType aValue )
{
switch( aValue )
{
case types::PadType::PT_PTH: return PAD_ATTRIB::PTH;
case types::PadType::PT_SMD: return PAD_ATTRIB::SMD;
case types::PadType::PT_EDGE_CONNECTOR: return PAD_ATTRIB::CONN;
case types::PadType::PT_NPTH: return PAD_ATTRIB::NPTH;
default:
wxCHECK_MSG( false, PAD_ATTRIB::PTH,
"Unhandled case in FromProtoEnum<types::PadType>" );
}
}
template<> template<>
types::PadStackShape ToProtoEnum( PAD_SHAPE aValue ) types::PadStackShape ToProtoEnum( PAD_SHAPE aValue )
{ {
@ -68,6 +102,70 @@ PAD_SHAPE FromProtoEnum( types::PadStackShape aValue )
} }
template<>
types::PadStackType ToProtoEnum( PADSTACK::MODE aValue )
{
switch( aValue )
{
case PADSTACK::MODE::NORMAL: return types::PadStackType::PST_NORMAL;
case PADSTACK::MODE::TOP_INNER_BOTTOM: return types::PadStackType::PST_TOP_INNER_BOTTOM;
case PADSTACK::MODE::CUSTOM: return types::PadStackType::PST_CUSTOM;
default:
wxCHECK_MSG( false, types::PadStackType::PST_UNKNOWN,
"Unhandled case in ToProtoEnum<PADSTACK::MODE>");
}
}
template<>
PADSTACK::MODE FromProtoEnum( types::PadStackType aValue )
{
switch( aValue )
{
case types::PadStackType::PST_NORMAL: return PADSTACK::MODE::NORMAL;
case types::PadStackType::PST_TOP_INNER_BOTTOM: return PADSTACK::MODE::TOP_INNER_BOTTOM;
case types::PadStackType::PST_CUSTOM: return PADSTACK::MODE::CUSTOM;
default:
wxCHECK_MSG( false, PADSTACK::MODE::NORMAL,
"Unhandled case in FromProtoEnum<types::PadStackType>" );
}
}
template<>
types::ViaType ToProtoEnum( VIATYPE aValue )
{
switch( aValue )
{
case VIATYPE::THROUGH: return types::ViaType::VT_THROUGH;
case VIATYPE::BLIND_BURIED: return types::ViaType::VT_BLIND_BURIED;
case VIATYPE::MICROVIA: return types::ViaType::VT_MICRO;
default:
wxCHECK_MSG( false, types::ViaType::VT_UNKNOWN,
"Unhandled case in ToProtoEnum<VIATYPE>");
}
}
template<>
VIATYPE FromProtoEnum( types::ViaType aValue )
{
switch( aValue )
{
case types::ViaType::VT_THROUGH: return VIATYPE::THROUGH;
case types::ViaType::VT_BLIND_BURIED: return VIATYPE::BLIND_BURIED;
case types::ViaType::VT_MICRO: return VIATYPE::MICROVIA;
default:
wxCHECK_MSG( false, VIATYPE::THROUGH,
"Unhandled case in FromProtoEnum<types::ViaType>" );
}
}
template<> template<>
types::ZoneConnectionStyle ToProtoEnum( ZONE_CONNECTION aValue ) types::ZoneConnectionStyle ToProtoEnum( ZONE_CONNECTION aValue )
{ {

View File

@ -73,7 +73,6 @@ PAD::PAD( FOOTPRINT* parent ) :
VECTOR2I& size = m_padStack.Size(); VECTOR2I& size = m_padStack.Size();
size.x = size.y = EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 60 ); // Default pad size 60 mils. size.x = size.y = EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 60 ); // Default pad size 60 mils.
drill.x = drill.y = EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 30 ); // Default drill size 30 mils. drill.x = drill.y = EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 30 ); // Default drill size 30 mils.
m_orient = ANGLE_0;
m_lengthPadToDie = 0; m_lengthPadToDie = 0;
if( m_parent && m_parent->Type() == PCB_FOOTPRINT_T ) if( m_parent && m_parent->Type() == PCB_FOOTPRINT_T )
@ -133,7 +132,8 @@ PAD& PAD::operator=( const PAD &aOther )
void PAD::Serialize( google::protobuf::Any &aContainer ) const void PAD::Serialize( google::protobuf::Any &aContainer ) const
{ {
kiapi::board::types::Pad pad; using namespace kiapi::board::types;
Pad pad;
pad.mutable_id()->set_value( m_Uuid.AsStdString() ); pad.mutable_id()->set_value( m_Uuid.AsStdString() );
kiapi::common::PackVector2( *pad.mutable_position(), GetPosition() ); kiapi::common::PackVector2( *pad.mutable_position(), GetPosition() );
@ -141,29 +141,13 @@ void PAD::Serialize( google::protobuf::Any &aContainer ) const
: kiapi::common::types::LockedState::LS_UNLOCKED ); : kiapi::common::types::LockedState::LS_UNLOCKED );
pad.mutable_net()->mutable_code()->set_value( GetNetCode() ); pad.mutable_net()->mutable_code()->set_value( GetNetCode() );
pad.mutable_net()->set_name( GetNetname() ); pad.mutable_net()->set_name( GetNetname() );
pad.set_type( ToProtoEnum<PAD_ATTRIB, PadType>( GetAttribute() ) );
kiapi::board::types::PadStack* padstack = pad.mutable_pad_stack(); google::protobuf::Any padStackMsg;
padstack->set_type( kiapi::board::types::PadStackType::PST_THROUGH ); m_padStack.Serialize( padStackMsg );
padstack->set_start_layer( padStackMsg.UnpackTo( pad.mutable_pad_stack() );
ToProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( m_layer ) );
padstack->set_end_layer(
ToProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( FlipLayer( m_layer ) ) );
kiapi::common::PackVector2( *padstack->mutable_drill_diameter(),
{ GetDrillSizeX(), GetDrillSizeY() } );
padstack->mutable_angle()->set_value_degrees( GetOrientationDegrees() );
kiapi::board::types::PadStackLayer* stackLayer = padstack->add_layers(); DesignRuleOverrides* overrides = pad.mutable_overrides();
kiapi::board::PackLayerSet( *stackLayer->mutable_layers(), GetLayerSet() );
kiapi::common::PackVector2( *stackLayer->mutable_size(),
{ GetSizeX(), GetSizeY() } );
stackLayer->set_shape(
ToProtoEnum<PAD_SHAPE, kiapi::board::types::PadStackShape>( GetShape() ) );
padstack->set_unconnected_layer_removal(
ToProtoEnum<PADSTACK::UNCONNECTED_LAYER_MODE,
kiapi::board::types::UnconnectedLayerRemoval>( GetUnconnectedLayerMode() ) );
kiapi::board::types::DesignRuleOverrides* overrides = pad.mutable_overrides();
if( GetLocalClearance().has_value() ) if( GetLocalClearance().has_value() )
overrides->mutable_clearance()->set_value_nm( *GetLocalClearance() ); overrides->mutable_clearance()->set_value_nm( *GetLocalClearance() );
@ -178,10 +162,9 @@ void PAD::Serialize( google::protobuf::Any &aContainer ) const
overrides->mutable_solder_paste_margin_ratio()->set_value( *GetLocalSolderPasteMarginRatio() ); overrides->mutable_solder_paste_margin_ratio()->set_value( *GetLocalSolderPasteMarginRatio() );
overrides->set_zone_connection( overrides->set_zone_connection(
ToProtoEnum<ZONE_CONNECTION, ToProtoEnum<ZONE_CONNECTION, ZoneConnectionStyle>( GetLocalZoneConnection() ) );
kiapi::board::types::ZoneConnectionStyle>( GetLocalZoneConnection() ) );
kiapi::board::types::ThermalSpokeSettings* thermals = pad.mutable_thermal_spokes(); ThermalSpokeSettings* thermals = pad.mutable_thermal_spokes();
thermals->set_width( GetThermalSpokeWidth() ); thermals->set_width( GetThermalSpokeWidth() );
thermals->set_gap( GetThermalGap() ); thermals->set_gap( GetThermalGap() );
@ -202,26 +185,13 @@ bool PAD::Deserialize( const google::protobuf::Any &aContainer )
SetPosition( kiapi::common::UnpackVector2( pad.position() ) ); SetPosition( kiapi::common::UnpackVector2( pad.position() ) );
SetNetCode( pad.net().code().value() ); SetNetCode( pad.net().code().value() );
SetLocked( pad.locked() == kiapi::common::types::LockedState::LS_LOCKED ); SetLocked( pad.locked() == kiapi::common::types::LockedState::LS_LOCKED );
SetAttribute( FromProtoEnum<PAD_ATTRIB>( pad.type() ) );
const kiapi::board::types::PadStack& padstack = pad.pad_stack(); google::protobuf::Any padStackWrapper;
padStackWrapper.PackFrom( pad.pad_stack() );
m_padStack.Deserialize( padStackWrapper );
SetLayer( FromProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( SetLayer( m_padStack.StartLayer() );
padstack.start_layer() ) );
SetDrillSize( kiapi::common::UnpackVector2( padstack.drill_diameter() ) );
SetOrientationDegrees( padstack.angle().value_degrees() );
// We don't yet support complex padstacks
if( padstack.layers_size() == 1 )
{
const kiapi::board::types::PadStackLayer& layer = padstack.layers( 0 );
SetSize( kiapi::common::UnpackVector2( layer.size() ) );
SetLayerSet( kiapi::board::UnpackLayerSet( layer.layers() ) );
SetShape( FromProtoEnum<PAD_SHAPE>( layer.shape() ) );
}
SetUnconnectedLayerMode(
FromProtoEnum<PADSTACK::UNCONNECTED_LAYER_MODE>( padstack.unconnected_layer_removal() ) );
const kiapi::board::types::DesignRuleOverrides& overrides = pad.overrides(); const kiapi::board::types::DesignRuleOverrides& overrides = pad.overrides();
@ -584,7 +554,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
VECTOR2I half_size = size / 2; VECTOR2I half_size = size / 2;
int half_width = std::min( half_size.x, half_size.y ); int half_width = std::min( half_size.x, half_size.y );
VECTOR2I half_len( half_size.x - half_width, half_size.y - half_width ); VECTOR2I half_len( half_size.x - half_width, half_size.y - half_width );
RotatePoint( half_len, m_orient ); RotatePoint( half_len, GetOrientation() );
add( new SHAPE_SEGMENT( shapePos - half_len, shapePos + half_len, half_width * 2 ) ); add( new SHAPE_SEGMENT( shapePos - half_len, shapePos + half_len, half_width * 2 ) );
} }
@ -624,7 +594,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
corners.Append( half_size.x - trap_delta.y, -half_size.y + trap_delta.x ); corners.Append( half_size.x - trap_delta.y, -half_size.y + trap_delta.x );
corners.Append( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x ); corners.Append( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x );
corners.Rotate( m_orient ); corners.Rotate( GetOrientation() );
corners.Move( shapePos ); corners.Move( shapePos );
// GAL renders rectangles faster than 4-point polygons so it's worth checking if our // GAL renders rectangles faster than 4-point polygons so it's worth checking if our
@ -669,7 +639,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, shapePos, GetSize(), m_orient, TransformRoundChamferedRectToPolygon( outline, shapePos, GetSize(), GetOrientation(),
GetRoundRectCornerRadius(), GetChamferRectRatio(), GetRoundRectCornerRadius(), GetChamferRectRatio(),
GetChamferPositions(), 0, maxError, ERROR_INSIDE ); GetChamferPositions(), 0, maxError, ERROR_INSIDE );
@ -691,7 +661,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
{ {
for( SHAPE* shape : primitive->MakeEffectiveShapes() ) for( SHAPE* shape : primitive->MakeEffectiveShapes() )
{ {
shape->Rotate( m_orient ); shape->Rotate( GetOrientation() );
shape->Move( shapePos ); shape->Move( shapePos );
add( shape ); add( shape );
} }
@ -706,7 +676,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const
int half_width = std::min( half_size.x, half_size.y ); int half_width = std::min( half_size.x, half_size.y );
VECTOR2I half_len( half_size.x - half_width, half_size.y - half_width ); VECTOR2I half_len( half_size.x - half_width, half_size.y - half_width );
RotatePoint( half_len, m_orient ); RotatePoint( half_len, GetOrientation() );
m_effectiveHoleShape = std::make_shared<SHAPE_SEGMENT>( m_pos - half_len, m_pos + half_len, m_effectiveHoleShape = std::make_shared<SHAPE_SEGMENT>( m_pos - half_len, m_pos + half_len,
half_width * 2 ); half_width * 2 );
@ -827,9 +797,7 @@ void PAD::SetProperty( PAD_PROP aProperty )
void PAD::SetOrientation( const EDA_ANGLE& aAngle ) void PAD::SetOrientation( const EDA_ANGLE& aAngle )
{ {
m_orient = aAngle; m_padStack.SetOrientation( aAngle );
m_orient.Normalize();
SetDirty(); SetDirty();
} }
@ -928,7 +896,7 @@ VECTOR2I PAD::ShapePos() const
VECTOR2I loc_offset = m_padStack.Offset(); VECTOR2I loc_offset = m_padStack.Offset();
RotatePoint( loc_offset, m_orient ); RotatePoint( loc_offset, GetOrientation() );
VECTOR2I shape_pos = m_pos + loc_offset; VECTOR2I shape_pos = m_pos + loc_offset;
@ -1426,9 +1394,7 @@ int PAD::Compare( const PAD* aPadRef, const PAD* aPadCmp )
void PAD::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) void PAD::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
{ {
RotatePoint( m_pos, aRotCentre, aAngle ); RotatePoint( m_pos, aRotCentre, aAngle );
m_padStack.SetOrientation( m_padStack.GetOrientation() + aAngle );
m_orient += aAngle;
m_orient.Normalize();
SetDirty(); SetDirty();
} }
@ -1828,7 +1794,7 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
int half_width = std::min( dx, dy ); int half_width = std::min( dx, dy );
VECTOR2I delta( dx - half_width, dy - half_width ); VECTOR2I delta( dx - half_width, dy - half_width );
RotatePoint( delta, m_orient ); RotatePoint( delta, GetOrientation() );
TransformOvalToPolygon( aBuffer, padShapePos - delta, padShapePos + delta, TransformOvalToPolygon( aBuffer, padShapePos - delta, padShapePos + delta,
( half_width + aClearance ) * 2, aMaxError, aErrorLoc, ( half_width + aClearance ) * 2, aMaxError, aErrorLoc,
@ -1844,8 +1810,8 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
int ddy = GetShape() == PAD_SHAPE::TRAPEZOID ? m_padStack.TrapezoidDeltaSize().y / 2 : 0; int ddy = GetShape() == PAD_SHAPE::TRAPEZOID ? m_padStack.TrapezoidDeltaSize().y / 2 : 0;
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
TransformTrapezoidToPolygon( outline, padShapePos, m_padStack.Size(), m_orient, ddx, ddy, aClearance, TransformTrapezoidToPolygon( outline, padShapePos, m_padStack.Size(), GetOrientation(), ddx,
aMaxError, aErrorLoc ); ddy, aClearance, aMaxError, aErrorLoc );
aBuffer.Append( outline ); aBuffer.Append( outline );
break; break;
} }
@ -1856,8 +1822,8 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
bool doChamfer = GetShape() == PAD_SHAPE::CHAMFERED_RECT; bool doChamfer = GetShape() == PAD_SHAPE::CHAMFERED_RECT;
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, padShapePos, m_padStack.Size(), m_orient, TransformRoundChamferedRectToPolygon( outline, padShapePos, m_padStack.Size(),
GetRoundRectCornerRadius(), GetOrientation(), GetRoundRectCornerRadius(),
doChamfer ? GetChamferRectRatio() : 0, doChamfer ? GetChamferRectRatio() : 0,
doChamfer ? GetChamferPositions() : 0, doChamfer ? GetChamferPositions() : 0,
aClearance, aMaxError, aErrorLoc ); aClearance, aMaxError, aErrorLoc );
@ -1869,7 +1835,7 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
{ {
SHAPE_POLY_SET outline; SHAPE_POLY_SET outline;
MergePrimitivesAsPolygon( &outline, aErrorLoc ); MergePrimitivesAsPolygon( &outline, aErrorLoc );
outline.Rotate( m_orient ); outline.Rotate( GetOrientation() );
outline.Move( VECTOR2I( padShapePos ) ); outline.Move( VECTOR2I( padShapePos ) );
if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE ) if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE )

View File

@ -355,7 +355,7 @@ public:
/** /**
* Return the rotation angle of the pad. * Return the rotation angle of the pad.
*/ */
EDA_ANGLE GetOrientation() const { return m_orient; } EDA_ANGLE GetOrientation() const { return m_padStack.GetOrientation(); }
EDA_ANGLE GetFPRelativeOrientation() const; EDA_ANGLE GetFPRelativeOrientation() const;
// For property system // For property system
@ -365,7 +365,7 @@ public:
} }
double GetOrientationDegrees() const double GetOrientationDegrees() const
{ {
return m_orient.AsDegrees(); return m_padStack.GetOrientation().AsDegrees();
} }
void SetDrillShape( PAD_DRILL_SHAPE aShape ) void SetDrillShape( PAD_DRILL_SHAPE aShape )
@ -867,8 +867,6 @@ private:
PAD_PROP m_property; // Property in fab files (BGA, FIDUCIAL, TESTPOINT, etc.) PAD_PROP m_property; // Property in fab files (BGA, FIDUCIAL, TESTPOINT, etc.)
EDA_ANGLE m_orient;
int m_lengthPadToDie; // Length net from pad to die, inside the package int m_lengthPadToDie; // Length net from pad to die, inside the package
std::mutex m_zoneLayerOverridesMutex; std::mutex m_zoneLayerOverridesMutex;

View File

@ -20,10 +20,15 @@
#include <convert_basic_shapes_to_polygon.h> // RECT_CHAMFER_POSITIONS #include <convert_basic_shapes_to_polygon.h> // RECT_CHAMFER_POSITIONS
#include "padstack.h" #include "padstack.h"
#include <api/api_enums.h>
#include <api/api_utils.h>
#include <api/api_pcb_utils.h>
#include <api/board/board_types.pb.h>
PADSTACK::PADSTACK() : PADSTACK::PADSTACK() :
m_mode( MODE::NORMAL ), m_mode( MODE::NORMAL ),
m_orientation( ANGLE_0 ),
m_unconnectedLayerMode( UNCONNECTED_LAYER_MODE::KEEP_ALL ), m_unconnectedLayerMode( UNCONNECTED_LAYER_MODE::KEEP_ALL ),
m_customShapeInZoneMode( CUSTOM_SHAPE_ZONE_MODE::OUTLINE ) m_customShapeInZoneMode( CUSTOM_SHAPE_ZONE_MODE::OUTLINE )
{ {
@ -83,12 +88,83 @@ bool PADSTACK::operator==( const PADSTACK& aOther ) const
bool PADSTACK::Deserialize( const google::protobuf::Any& aContainer ) bool PADSTACK::Deserialize( const google::protobuf::Any& aContainer )
{ {
using namespace kiapi::board::types;
PadStack padstack;
if( !aContainer.UnpackTo( &padstack ) )
return false; return false;
m_mode = FromProtoEnum<MODE>( padstack.type() );
// TODO
m_layerSet.reset();
m_orientation = EDA_ANGLE( padstack.angle().value_degrees(), DEGREES_T );
Drill().size = kiapi::common::UnpackVector2( padstack.drill_diameter() );
Drill().start = FromProtoEnum<PCB_LAYER_ID>( padstack.start_layer() );
Drill().end = FromProtoEnum<PCB_LAYER_ID>( padstack.end_layer() );
// We don't yet support complex padstacks
if( padstack.layers_size() == 1 )
{
const PadStackLayer& layer = padstack.layers( 0 );
Size() = kiapi::common::UnpackVector2( layer.size() );
SetLayerSet( kiapi::board::UnpackLayerSet( layer.layers() ) );
SetShape( FromProtoEnum<PAD_SHAPE>( layer.shape() ) );
SHAPE_PROPS& props = CopperLayerDefaults().shape;
props.chamfered_rect_ratio = layer.chamfer_ratio();
props.round_rect_radius_ratio = layer.corner_rounding_ratio();
if( layer.chamfered_corners().top_left() )
props.chamfered_rect_positions |= RECT_CHAMFER_TOP_LEFT;
if( layer.chamfered_corners().top_right() )
props.chamfered_rect_positions |= RECT_CHAMFER_TOP_RIGHT;
if( layer.chamfered_corners().bottom_left() )
props.chamfered_rect_positions |= RECT_CHAMFER_BOTTOM_LEFT;
if( layer.chamfered_corners().bottom_right() )
props.chamfered_rect_positions |= RECT_CHAMFER_BOTTOM_RIGHT;
}
SetUnconnectedLayerMode(
FromProtoEnum<UNCONNECTED_LAYER_MODE>( padstack.unconnected_layer_removal() ) );
return true;
} }
void PADSTACK::Serialize( google::protobuf::Any& aContainer ) const void PADSTACK::Serialize( google::protobuf::Any& aContainer ) const
{ {
using namespace kiapi::board::types;
PadStack padstack;
padstack.set_type( ToProtoEnum<MODE, PadStackType>( m_mode ) );
padstack.set_start_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( StartLayer() ) );
padstack.set_end_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( EndLayer() ) );
kiapi::common::PackVector2( *padstack.mutable_drill_diameter(), Drill().size );
padstack.mutable_angle()->set_value_degrees( m_orientation.AsDegrees() );
PadStackLayer* stackLayer = padstack.add_layers();
kiapi::board::PackLayerSet( *stackLayer->mutable_layers(), LayerSet() );
kiapi::common::PackVector2( *stackLayer->mutable_size(), Size() );
stackLayer->set_shape( ToProtoEnum<PAD_SHAPE, PadStackShape>( Shape() ) );
stackLayer->set_chamfer_ratio( CopperLayerDefaults().shape.chamfered_rect_ratio );
stackLayer->set_corner_rounding_ratio( CopperLayerDefaults().shape.round_rect_radius_ratio );
const int& corners = CopperLayerDefaults().shape.chamfered_rect_positions;
stackLayer->mutable_chamfered_corners()->set_top_left( corners & RECT_CHAMFER_TOP_LEFT );
stackLayer->mutable_chamfered_corners()->set_top_right( corners & RECT_CHAMFER_TOP_RIGHT );
stackLayer->mutable_chamfered_corners()->set_bottom_left( corners & RECT_CHAMFER_BOTTOM_LEFT );
stackLayer->mutable_chamfered_corners()->set_bottom_right( corners & RECT_CHAMFER_BOTTOM_RIGHT );
padstack.set_unconnected_layer_removal(
ToProtoEnum<UNCONNECTED_LAYER_MODE, UnconnectedLayerRemoval>( m_unconnectedLayerMode ) );
aContainer.PackFrom( padstack );
} }
@ -99,6 +175,18 @@ wxString PADSTACK::Name() const
} }
PCB_LAYER_ID PADSTACK::StartLayer() const
{
return m_drill.start;
}
PCB_LAYER_ID PADSTACK::EndLayer() const
{
return m_drill.end;
}
PADSTACK::SHAPE_PROPS::SHAPE_PROPS() : PADSTACK::SHAPE_PROPS::SHAPE_PROPS() :
shape( PAD_SHAPE::CIRCLE ), shape( PAD_SHAPE::CIRCLE ),
anchor_shape( PAD_SHAPE::CIRCLE ), anchor_shape( PAD_SHAPE::CIRCLE ),

View File

@ -241,9 +241,22 @@ public:
LSET& LayerSet() { return m_layerSet; } LSET& LayerSet() { return m_layerSet; }
void SetLayerSet( const LSET& aSet ) { m_layerSet = aSet; } void SetLayerSet( const LSET& aSet ) { m_layerSet = aSet; }
PCB_LAYER_ID StartLayer() const;
PCB_LAYER_ID EndLayer() const;
MODE Mode() const { return m_mode; }
void SetMode( MODE aMode ) { m_mode = aMode; }
///! Returns the name of this padstack in IPC-7351 format ///! Returns the name of this padstack in IPC-7351 format
wxString Name() const; wxString Name() const;
EDA_ANGLE GetOrientation() const { return m_orientation; }
void SetOrientation( EDA_ANGLE aAngle )
{
m_orientation = aAngle;
m_orientation.Normalize();
}
DRILL_PROPS& Drill() { return m_drill; } DRILL_PROPS& Drill() { return m_drill; }
const DRILL_PROPS& Drill() const { return m_drill; } const DRILL_PROPS& Drill() const { return m_drill; }
@ -329,6 +342,9 @@ private:
///! An override for the IPC-7351 padstack name ///! An override for the IPC-7351 padstack name
wxString m_customName; wxString m_customName;
///! The rotation of the pad relative to an outer reference frame
EDA_ANGLE m_orientation;
///! The properties applied to copper layers if they aren't overridden ///! The properties applied to copper layers if they aren't overridden
COPPER_LAYER_PROPS m_defaultCopperProps; COPPER_LAYER_PROPS m_defaultCopperProps;

View File

@ -168,8 +168,7 @@ bool PCB_TEXT::Deserialize( const google::protobuf::Any &aContainer )
attrs.m_Angle = EDA_ANGLE( text.attributes().angle().value_degrees(), DEGREES_T ); attrs.m_Angle = EDA_ANGLE( text.attributes().angle().value_degrees(), DEGREES_T );
attrs.m_LineSpacing = text.attributes().line_spacing(); attrs.m_LineSpacing = text.attributes().line_spacing();
SetTextThickness( text.attributes().stroke_width().value_nm() ); attrs.m_StrokeWidth = text.attributes().stroke_width().value_nm();
attrs.m_Halign = FromProtoEnum<GR_TEXT_H_ALIGN_T, types::HorizontalAlignment>( attrs.m_Halign = FromProtoEnum<GR_TEXT_H_ALIGN_T, types::HorizontalAlignment>(
text.attributes().horizontal_alignment() ); text.attributes().horizontal_alignment() );

View File

@ -90,7 +90,13 @@ PCB_VIA::PCB_VIA( BOARD_ITEM* aParent ) :
Padstack().Drill().end = B_Cu; Padstack().Drill().end = B_Cu;
SetDrillDefault(); SetDrillDefault();
Padstack().SetUnconnectedLayerMode( PADSTACK::UNCONNECTED_LAYER_MODE::KEEP_ALL ); m_padStack.SetUnconnectedLayerMode( PADSTACK::UNCONNECTED_LAYER_MODE::KEEP_ALL );
// Until vias support custom padstack; their layer set should always be cleared
m_padStack.LayerSet().reset();
// For now, vias are always circles
m_padStack.SetShape( PAD_SHAPE::CIRCLE );
m_zoneLayerOverrides.fill( ZLO_NONE ); m_zoneLayerOverrides.fill( ZLO_NONE );
@ -375,31 +381,19 @@ void PCB_VIA::Serialize( google::protobuf::Any &aContainer ) const
via.mutable_position()->set_x_nm( GetPosition().x ); via.mutable_position()->set_x_nm( GetPosition().x );
via.mutable_position()->set_y_nm( GetPosition().y ); via.mutable_position()->set_y_nm( GetPosition().y );
const PADSTACK& stack = Padstack(); PADSTACK padstack = Padstack();
kiapi::board::types::PadStack* padstack = via.mutable_pad_stack(); // Via width is currently stored in PCB_TRACK::m_Width rather than in the
padstack->set_type( GetViaType() == VIATYPE::BLIND_BURIED // padstack object; so hack it in here unless/until that changes
? kiapi::board::types::PadStackType::PST_BLIND_BURIED padstack.Size() = { m_Width, m_Width };
: kiapi::board::types::PadStackType::PST_THROUGH );
padstack->set_start_layer(
ToProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( stack.Drill().start ) );
padstack->set_end_layer(
ToProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( stack.Drill().end ) );
kiapi::common::PackVector2( *padstack->mutable_drill_diameter(),
{ GetDrillValue(), GetDrillValue() } );
kiapi::board::types::PadStackLayer* stackLayer = padstack->add_layers(); google::protobuf::Any padStackWrapper;
kiapi::board::PackLayerSet( *stackLayer->mutable_layers(), GetLayerSet() ); padstack.Serialize( padStackWrapper );
kiapi::common::PackVector2( *stackLayer->mutable_size(), padStackWrapper.UnpackTo( via.mutable_pad_stack() );
{ GetWidth(), GetWidth() } );
// TODO: Microvia status is ignored here. Do we still need it?
padstack->set_unconnected_layer_removal(
ToProtoEnum<PADSTACK::UNCONNECTED_LAYER_MODE,
kiapi::board::types::UnconnectedLayerRemoval>(
Padstack().UnconnectedLayerMode() ) );
via.set_type( ToProtoEnum<VIATYPE, kiapi::board::types::ViaType>( GetViaType() ) );
via.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED via.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
: kiapi::common::types::LockedState::LS_UNLOCKED ); : kiapi::common::types::LockedState::LS_UNLOCKED );
via.mutable_net()->mutable_code()->set_value( GetNetCode() ); via.mutable_net()->mutable_code()->set_value( GetNetCode() );
@ -421,42 +415,15 @@ bool PCB_VIA::Deserialize( const google::protobuf::Any &aContainer )
SetEnd( GetStart() ); SetEnd( GetStart() );
SetDrill( via.pad_stack().drill_diameter().x_nm() ); SetDrill( via.pad_stack().drill_diameter().x_nm() );
const kiapi::board::types::PadStack& padstack = via.pad_stack(); google::protobuf::Any padStackWrapper;
padStackWrapper.PackFrom( via.pad_stack() );
if( !m_padStack.Deserialize( padStackWrapper ) )
return false;
// We don't yet support complex padstacks for vias // We don't yet support complex padstacks for vias
if( padstack.layers_size() == 1 ) SetWidth( m_padStack.Size().x );
{ SetViaType( FromProtoEnum<VIATYPE>( via.type() ) );
const kiapi::board::types::PadStackLayer& layer = padstack.layers( 0 );
SetWidth( layer.size().x_nm() );
}
switch( padstack.type() )
{
case kiapi::board::types::PadStackType::PST_BLIND_BURIED:
SetViaType( VIATYPE::BLIND_BURIED );
break;
default:
SetViaType( VIATYPE::THROUGH );
break;
}
if( GetViaType() != VIATYPE::THROUGH )
{
Padstack().Drill().start = FromProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>(
padstack.start_layer() );
Padstack().Drill().end = FromProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>(
padstack.end_layer() );
}
else
{
Padstack().Drill().start = F_Cu;
Padstack().Drill().end = B_Cu;
}
Padstack().SetUnconnectedLayerMode( FromProtoEnum<PADSTACK::UNCONNECTED_LAYER_MODE>(
padstack.unconnected_layer_removal() ) );
SetNetCode( via.net().code().value() ); SetNetCode( via.net().code().value() );
SetLocked( via.locked() == kiapi::common::types::LockedState::LS_LOCKED ); SetLocked( via.locked() == kiapi::common::types::LockedState::LS_LOCKED );

View File

@ -0,0 +1,879 @@
(kicad_pcb
(version 20240108)
(generator "pcbnew")
(generator_version "8.0")
(general
(thickness 1.6)
(legacy_teardrops no)
)
(paper "A4")
(layers
(0 "F.Cu" signal)
(1 "In1.Cu" signal)
(2 "In2.Cu" signal)
(3 "In3.Cu" signal)
(4 "In4.Cu" signal)
(31 "B.Cu" signal)
(32 "B.Adhes" user "B.Adhesive")
(33 "F.Adhes" user "F.Adhesive")
(34 "B.Paste" user)
(35 "F.Paste" user)
(36 "B.SilkS" user "B.Silkscreen")
(37 "F.SilkS" user "F.Silkscreen")
(38 "B.Mask" user)
(39 "F.Mask" user)
(40 "Dwgs.User" user "User.Drawings")
(41 "Cmts.User" user "User.Comments")
(42 "Eco1.User" user "User.Eco1")
(43 "Eco2.User" user "User.Eco2")
(44 "Edge.Cuts" user)
(45 "Margin" user)
(46 "B.CrtYd" user "B.Courtyard")
(47 "F.CrtYd" user "F.Courtyard")
(48 "B.Fab" user)
(49 "F.Fab" user)
(50 "User.1" user)
(51 "User.2" user)
(52 "User.3" user)
(53 "User.4" user)
(54 "User.5" user)
(55 "User.6" user)
(56 "User.7" user)
(57 "User.8" user)
(58 "User.9" user)
)
(setup
(stackup
(layer "F.SilkS"
(type "Top Silk Screen")
)
(layer "F.Paste"
(type "Top Solder Paste")
)
(layer "F.Mask"
(type "Top Solder Mask")
(thickness 0.01)
)
(layer "F.Cu"
(type "copper")
(thickness 0.035)
)
(layer "dielectric 1"
(type "prepreg")
(thickness 0.1)
(material "FR4")
(epsilon_r 4.5)
(loss_tangent 0.02)
)
(layer "In1.Cu"
(type "copper")
(thickness 0.035)
)
(layer "dielectric 2"
(type "core")
(thickness 0.535)
(material "FR4")
(epsilon_r 4.5)
(loss_tangent 0.02)
)
(layer "In2.Cu"
(type "copper")
(thickness 0.035)
)
(layer "dielectric 3"
(type "prepreg")
(thickness 0.1)
(material "FR4")
(epsilon_r 4.5)
(loss_tangent 0.02)
)
(layer "In3.Cu"
(type "copper")
(thickness 0.035)
)
(layer "dielectric 4"
(type "core")
(thickness 0.535)
(material "FR4")
(epsilon_r 4.5)
(loss_tangent 0.02)
)
(layer "In4.Cu"
(type "copper")
(thickness 0.035)
)
(layer "dielectric 5"
(type "prepreg")
(thickness 0.1)
(material "FR4")
(epsilon_r 4.5)
(loss_tangent 0.02)
)
(layer "B.Cu"
(type "copper")
(thickness 0.035)
)
(layer "B.Mask"
(type "Bottom Solder Mask")
(thickness 0.01)
)
(layer "B.Paste"
(type "Bottom Solder Paste")
)
(layer "B.SilkS"
(type "Bottom Silk Screen")
)
(copper_finish "None")
(dielectric_constraints no)
)
(pad_to_mask_clearance 0)
(allow_soldermask_bridges_in_footprints no)
(pcbplotparams
(layerselection 0x00010fc_ffffffff)
(plot_on_all_layers_selection 0x0000000_00000000)
(disableapertmacros no)
(usegerberextensions no)
(usegerberattributes yes)
(usegerberadvancedattributes yes)
(creategerberjobfile yes)
(dashed_line_dash_ratio 12.000000)
(dashed_line_gap_ratio 3.000000)
(svgprecision 4)
(plotframeref no)
(viasonmask no)
(mode 1)
(useauxorigin no)
(hpglpennumber 1)
(hpglpenspeed 20)
(hpglpendiameter 15.000000)
(pdf_front_fp_property_popups yes)
(pdf_back_fp_property_popups yes)
(dxfpolygonmode yes)
(dxfimperialunits yes)
(dxfusepcbnewfont yes)
(psnegative no)
(psa4output no)
(plotreference yes)
(plotvalue yes)
(plotfptext yes)
(plotinvisibletext no)
(sketchpadsonfab no)
(subtractmaskfromsilk no)
(outputformat 1)
(mirror no)
(drillshape 1)
(scaleselection 1)
(outputdirectory "")
)
)
(net 0 "")
(net 1 "A")
(net 2 "B")
(footprint "TestPoint:TestPoint_Pad_D2.0mm"
(layer "F.Cu")
(uuid "0c12f606-2e6b-4b10-8aee-13ada275880a")
(at 125 89)
(descr "SMD pad as test Point, diameter 2.0mm")
(tags "test point SMD pad")
(property "Reference" "P2"
(at 0 -1.998 0)
(layer "F.SilkS")
(uuid "29533062-1c68-45f1-aa62-808c999e5f83")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Value" "TestPoint_Pad_D2.0mm"
(at 0 2.05 0)
(layer "F.Fab")
(hide yes)
(uuid "fd646f0b-5dc3-467c-97d3-06db9fc43f63")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Footprint" "TestPoint:TestPoint_Pad_D2.0mm"
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "77760901-137c-4ad1-95fd-8bca92e130f9")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(property "Datasheet" ""
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "160cf796-ce2e-44d6-b25d-7cde236f4252")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(property "Description" ""
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "4a70b60d-a7c8-4815-afbf-9d244e28b40a")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(attr exclude_from_pos_files exclude_from_bom)
(fp_circle
(center 0 0)
(end 0 1.2)
(stroke
(width 0.12)
(type solid)
)
(fill none)
(layer "F.SilkS")
(uuid "c03d6f26-7038-4706-b2fb-d9a9feae2ab3")
)
(fp_circle
(center 0 0)
(end 1.5 0)
(stroke
(width 0.05)
(type solid)
)
(fill none)
(layer "F.CrtYd")
(uuid "04545c49-ee36-461e-8b2e-f8747ad85b16")
)
(fp_text user "${REFERENCE}"
(at 0 -2 0)
(layer "F.Fab")
(uuid "6387eca8-2e8b-45cc-b457-5fdbc4a80b3f")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(pad "1" smd circle
(at 0 0 90)
(size 2 2)
(layers "F.Cu" "F.Mask")
(uuid "d37584cd-2e2f-40b5-822b-12791118953d")
)
)
(footprint "TestPoint:TestPoint_Pad_D2.0mm"
(layer "F.Cu")
(uuid "516f904c-b21d-49d3-bbc4-a9b97f897bb1")
(at 137 89)
(descr "SMD pad as test Point, diameter 2.0mm")
(tags "test point SMD pad")
(property "Reference" "P5"
(at 0 -1.998 0)
(layer "F.SilkS")
(uuid "68cba2b6-b596-4711-a20c-f5aace777c21")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Value" "TestPoint_Pad_D2.0mm"
(at 0 2.05 0)
(layer "F.Fab")
(hide yes)
(uuid "6f02e655-dc34-4a7e-bd71-f79a95274878")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Footprint" "TestPoint:TestPoint_Pad_D2.0mm"
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "b44ac9da-098a-4f00-9ae0-9e18cb78e77b")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(property "Datasheet" ""
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "9b63f67d-c7d1-440b-9109-21f26fc865ba")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(property "Description" ""
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "1eb2de7a-10c7-45c6-9b2b-f1878805e977")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(attr exclude_from_pos_files exclude_from_bom)
(fp_circle
(center 0 0)
(end 0 1.2)
(stroke
(width 0.12)
(type solid)
)
(fill none)
(layer "F.SilkS")
(uuid "9cb364d6-bc28-4600-8690-1945a69b4efe")
)
(fp_circle
(center 0 0)
(end 1.5 0)
(stroke
(width 0.05)
(type solid)
)
(fill none)
(layer "F.CrtYd")
(uuid "2aacb056-b289-4231-8a9b-cdad899fcc6e")
)
(fp_text user "${REFERENCE}"
(at 0 -2 0)
(layer "F.Fab")
(uuid "874081cb-e656-419e-8c45-68e819c6b71a")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(pad "2" smd trapezoid
(at 0 0 315)
(size 3 2)
(rect_delta 1 0)
(layers "F.Cu" "F.Paste" "F.Mask")
(uuid "f98951ae-c7c4-445b-a39a-a4d57888a02e")
)
)
(footprint "TestPoint:TestPoint_Pad_D2.0mm"
(layer "F.Cu")
(uuid "72233f75-c54b-4983-a966-c01867960037")
(at 133 89)
(descr "SMD pad as test Point, diameter 2.0mm")
(tags "test point SMD pad")
(property "Reference" "P4"
(at 0 -1.998 0)
(layer "F.SilkS")
(uuid "50769063-424e-4393-a2a5-8a4afc86a5f6")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Value" "TestPoint_Pad_D2.0mm"
(at 0 2.05 0)
(layer "F.Fab")
(hide yes)
(uuid "a1a75197-03e0-4e76-b27f-4926bc09a754")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Footprint" "TestPoint:TestPoint_Pad_D2.0mm"
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "ba936de1-036a-4248-bbb7-91ef95178a8b")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(property "Datasheet" ""
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "8187b195-b69e-4768-b5fb-4705d21fdeaf")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(property "Description" ""
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "b711170d-a950-461d-b38d-8189914c26ae")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(attr exclude_from_pos_files exclude_from_bom)
(fp_circle
(center 0 0)
(end 0 1.2)
(stroke
(width 0.12)
(type solid)
)
(fill none)
(layer "F.SilkS")
(uuid "92f6ddd2-345a-488f-826f-c01d36d10578")
)
(fp_circle
(center 0 0)
(end 1.5 0)
(stroke
(width 0.05)
(type solid)
)
(fill none)
(layer "F.CrtYd")
(uuid "81f7d7e8-fc1c-401b-9a37-f0bcb4a35e24")
)
(fp_text user "${REFERENCE}"
(at 0 -2 0)
(layer "F.Fab")
(uuid "34183372-a393-435e-b4af-f67d0575d11d")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(pad "Pad" smd roundrect
(at 0 0 45)
(size 3 2)
(layers "F.Cu" "F.Paste" "F.Mask")
(roundrect_rratio 0.1)
(chamfer_ratio 0.21)
(chamfer top_left bottom_right)
(uuid "1ad1d3ed-e8f5-4c7f-b0f6-095051a53b11")
)
)
(footprint "TestPoint:TestPoint_Pad_D2.0mm"
(layer "F.Cu")
(uuid "bccaa590-e277-424e-9452-8ccb31862c88")
(at 121 89)
(descr "SMD pad as test Point, diameter 2.0mm")
(tags "test point SMD pad")
(property "Reference" "P1"
(at 0 -1.998 0)
(layer "F.SilkS")
(uuid "9c54587b-d5ae-4242-962b-6e199e7ffccc")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Value" "TestPoint_Pad_D2.0mm"
(at 0 2.05 0)
(layer "F.Fab")
(hide yes)
(uuid "58bd7580-ca97-467b-bc98-ab9f4296c399")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Footprint" "TestPoint:TestPoint_Pad_D2.0mm"
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "229a859d-ddeb-445e-b1c3-66df7fb9709f")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(property "Datasheet" ""
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "a7c735ac-7821-453f-8e0c-20b4a2668cd0")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(property "Description" ""
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "64a3ff2b-93a4-4db6-8b1f-6626b3972c84")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(attr exclude_from_pos_files exclude_from_bom)
(fp_circle
(center 0 0)
(end 0 1.2)
(stroke
(width 0.12)
(type solid)
)
(fill none)
(layer "F.SilkS")
(uuid "17b3c656-d3b6-4523-a217-6cc0c933bbc5")
)
(fp_circle
(center 0 0)
(end 1.5 0)
(stroke
(width 0.05)
(type solid)
)
(fill none)
(layer "F.CrtYd")
(uuid "bcf6e409-f396-4570-bbac-9a0bde9d6eb7")
)
(fp_text user "${REFERENCE}"
(at 0 -2 0)
(layer "F.Fab")
(uuid "70ccb569-831d-4f12-afe4-88c6c3d4e3b0")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(pad "1" smd circle
(at 0 0)
(size 2 2)
(layers "F.Cu" "F.Mask")
(uuid "bd1ca0c2-74bb-4a01-94e6-11796af0cb7e")
)
)
(footprint "TestPoint:TestPoint_Pad_D2.0mm"
(layer "F.Cu")
(uuid "ecc0fb0f-74be-4cd5-a2b5-2009c7f9f73c")
(at 129 89)
(descr "SMD pad as test Point, diameter 2.0mm")
(tags "test point SMD pad")
(property "Reference" "P3"
(at 0 -1.998 0)
(layer "F.SilkS")
(uuid "58ffde45-fba5-43db-8389-e047f26aab55")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Value" "TestPoint_Pad_D2.0mm"
(at 0 2.05 0)
(layer "F.Fab")
(hide yes)
(uuid "3f4c00bd-623b-4cdb-8124-59191148fa44")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(property "Footprint" "TestPoint:TestPoint_Pad_D2.0mm"
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "b732c943-e9ae-4147-aeb2-735f86b72eef")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(property "Datasheet" ""
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "17598608-0902-4805-a022-bd8da9235d0e")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(property "Description" ""
(at 0 0 0)
(unlocked yes)
(layer "F.Fab")
(hide yes)
(uuid "0ec04652-0134-49e1-9e4a-0e7f3dc101b0")
(effects
(font
(size 1.27 1.27)
(thickness 0.15)
)
)
)
(attr exclude_from_pos_files exclude_from_bom)
(fp_circle
(center 0 0)
(end 0 1.2)
(stroke
(width 0.12)
(type solid)
)
(fill none)
(layer "F.SilkS")
(uuid "7584de47-699d-4756-8eed-a1ffa89c7756")
)
(fp_circle
(center 0 0)
(end 1.5 0)
(stroke
(width 0.05)
(type solid)
)
(fill none)
(layer "F.CrtYd")
(uuid "b4644ae7-78b8-4b76-a571-5cad70b4d1ca")
)
(fp_text user "${REFERENCE}"
(at 0 -2 0)
(layer "F.Fab")
(uuid "b7d991b5-45bd-4a62-af88-db0c92e6a949")
(effects
(font
(size 1 1)
(thickness 0.15)
)
)
)
(pad "Pad" smd circle
(at 0 0 90)
(size 2 2)
(property pad_prop_bga)
(layers "F.Cu" "F.Paste" "F.Mask")
(die_length 1.8)
(uuid "d4769495-2985-428a-a206-5d90728f6d88")
)
)
(gr_rect
(start 118 78)
(end 146 106)
(stroke
(width 0.05)
(type default)
)
(fill none)
(layer "Edge.Cuts")
(uuid "5d1e8cc9-08f0-4cd1-a676-1faf146c0408")
)
(via blind
(at 128 80)
(size 0.6)
(drill 0.3)
(layers "F.Cu" "B.Cu")
(net 0)
(uuid "453c7569-dd77-45eb-bcc3-30db3a0f40a9")
)
(via blind
(at 128 81)
(size 0.6)
(drill 0.3)
(layers "In1.Cu" "In4.Cu")
(net 0)
(uuid "68434c33-7a9f-42fc-987d-91fe3a581387")
)
(via blind
(at 128 83)
(size 0.6)
(drill 0.3)
(layers "In2.Cu" "In3.Cu")
(net 0)
(uuid "13486125-e7d8-4fb9-bf37-cba2e8c45ed4")
)
(via blind
(at 128 82)
(size 0.6)
(drill 0.3)
(layers "In2.Cu" "In3.Cu")
(net 0)
(uuid "8b2bd992-9b12-4445-b400-250bd7889789")
)
(via
(at 120 80)
(size 0.6)
(drill 0.3)
(layers "F.Cu" "B.Cu")
(free yes)
(net 1)
(uuid "2ff08d6b-d2fa-498c-aa0a-437903b48438")
)
(via
(at 124 80)
(size 0.6)
(drill 0.3)
(layers "F.Cu" "B.Cu")
(free yes)
(net 1)
(uuid "b86ba856-d576-4a99-a8e8-6d1c7f1f8e54")
)
(via
(at 122 80)
(size 0.6)
(drill 0.3)
(layers "F.Cu" "B.Cu")
(free yes)
(net 2)
(uuid "4da21d74-ca51-4030-841d-9fa4271dd639")
)
(via
(at 122 82)
(size 0.7)
(drill 0.35)
(layers "F.Cu" "B.Cu")
(remove_unused_layers yes)
(keep_end_layers no)
(free yes)
(zone_layer_connections)
(teardrops
(best_length_ratio 0.2)
(max_length 0)
(best_width_ratio 0.8)
(max_width 10)
(curve_points 10)
(filter_ratio 0.75)
(enabled yes)
(allow_two_segments yes)
(prefer_zone_connections yes)
)
(net 2)
(uuid "c37863ac-f1db-49d4-876a-be127599ff62")
)
(via
(at 122 81)
(size 0.7)
(drill 0.35)
(layers "F.Cu" "B.Cu")
(remove_unused_layers yes)
(keep_end_layers yes)
(free yes)
(zone_layer_connections)
(teardrops
(best_length_ratio 0.42)
(max_length 0.75)
(best_width_ratio 1.01)
(max_width 2.3)
(curve_points 0)
(filter_ratio 0.85)
(enabled yes)
(allow_two_segments no)
(prefer_zone_connections yes)
)
(net 2)
(uuid "d8a5911f-c1d6-4713-912d-d31101496061")
)
(via micro
(at 126 80)
(size 0.2)
(drill 0.1)
(layers "F.Cu" "B.Cu")
(locked yes)
(free yes)
(net 2)
(uuid "dab5afb6-716e-4443-b91e-13650cfba71f")
)
(via micro
(at 126 81)
(size 0.2)
(drill 0.1)
(layers "F.Cu" "In4.Cu")
(locked yes)
(free yes)
(net 2)
(uuid "dd040225-30f9-4c79-ad3e-e43383b2fb35")
)
(via micro
(at 126 83)
(size 0.3)
(drill 0.1)
(layers "In3.Cu" "B.Cu")
(locked yes)
(free yes)
(net 2)
(uuid "878e8a3b-77d9-402e-9019-c139f6ee7548")
)
(via micro
(at 126 82)
(size 0.2)
(drill 0.1)
(layers "In4.Cu" "B.Cu")
(locked yes)
(free yes)
(net 2)
(uuid "c5a1f081-1841-48f2-858c-598a487445a0")
)
)

View File

@ -0,0 +1,273 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.05,
"copper_line_width": 0.2,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.05,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.1,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.1,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.0,
"height": 2.0,
"width": 3.0
},
"silk_line_width": 0.1,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.1,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.5
}
},
"diff_pair_dimensions": [],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_near_hole": "error",
"holes_co_located": "warning",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "warning",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.0,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.5,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.2,
"min_microvia_drill": 0.1,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.8,
"min_text_thickness": 0.08,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.0,
"min_via_annular_width": 0.1,
"min_via_diameter": 0.5,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": false,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [],
"zones_allow_external_fillets": false
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "padstacks.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.3,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"legacy_lib_dir": "",
"legacy_lib_list": []
},
"sheets": [],
"text_variables": {}
}

View File

@ -54,6 +54,8 @@ void testProtoFromKiCadObject( KiCadClass* aInput )
google::protobuf::Any any; google::protobuf::Any any;
BOOST_REQUIRE_NO_THROW( aInput->Serialize( any ) ); BOOST_REQUIRE_NO_THROW( aInput->Serialize( any ) );
BOOST_TEST_MESSAGE( "Input: " << any.Utf8DebugString() );
ProtoClass proto; ProtoClass proto;
BOOST_REQUIRE_MESSAGE( any.UnpackTo( &proto ), BOOST_REQUIRE_MESSAGE( any.UnpackTo( &proto ),
"Any message did not unpack into the requested type" ); "Any message did not unpack into the requested type" );
@ -67,18 +69,16 @@ void testProtoFromKiCadObject( KiCadClass* aInput )
// This round-trip checks that we can create an equivalent protobuf // This round-trip checks that we can create an equivalent protobuf
google::protobuf::Any outputAny; google::protobuf::Any outputAny;
BOOST_REQUIRE_NO_THROW( output.Serialize( outputAny ) ); BOOST_REQUIRE_NO_THROW( output.Serialize( outputAny ) );
BOOST_TEST_MESSAGE( "Output: " << outputAny.Utf8DebugString() );
if( !( outputAny.SerializeAsString() == any.SerializeAsString() ) ) if( !( outputAny.SerializeAsString() == any.SerializeAsString() ) )
{ {
BOOST_TEST_MESSAGE( "Input: " << any.Utf8DebugString() );
BOOST_TEST_MESSAGE( "Output: " << outputAny.Utf8DebugString() );
BOOST_TEST_FAIL( "Round-tripped protobuf does not match" ); BOOST_TEST_FAIL( "Round-tripped protobuf does not match" );
} }
// This round-trip checks that we can create an equivalent KiCad object // This round-trip checks that we can create an equivalent KiCad object
if( !( output == *aInput ) ) if( !( output == *aInput ) )
{ {
if( ( output == *aInput ) )
BOOST_TEST_MESSAGE("ha");
BOOST_TEST_FAIL( "Round-tripped object does not match" ); BOOST_TEST_FAIL( "Round-tripped object does not match" );
} }
} }
@ -118,4 +118,26 @@ BOOST_FIXTURE_TEST_CASE( BoardTypes, PROTO_TEST_FIXTURE )
// testProtoFromKiCadObject<kiapi::board::types::Zone>( zone ); // testProtoFromKiCadObject<kiapi::board::types::Zone>( zone );
} }
BOOST_FIXTURE_TEST_CASE( Padstacks, PROTO_TEST_FIXTURE )
{
KI_TEST::LoadBoard( m_settingsManager, "padstacks", m_board );
for( PCB_TRACK* track : m_board->Tracks() )
{
switch( track->Type() )
{
case PCB_VIA_T:
testProtoFromKiCadObject<kiapi::board::types::Via>( static_cast<PCB_VIA*>( track ) );
break;
default:
wxFAIL;
}
}
for( FOOTPRINT* footprint : m_board->Footprints() )
testProtoFromKiCadObject<kiapi::board::types::FootprintInstance>( footprint );
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()