KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_drc_backdrill_postmachining.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
24
27
28#include <board.h>
32#include <drc/drc_engine.h>
33#include <drc/drc_item.h>
34#include <footprint.h>
35#include <pad.h>
36#include <pcb_track.h>
37#include <pcb_marker.h>
39#include <zone.h>
40#include <zone_filler.h>
41
42
44{
46 {
47 m_board = std::make_unique<BOARD>();
49 }
50
52 {
53 // Set up a 6-layer board with proper stackup for layer distance calculations
54 m_board->SetCopperLayerCount( 6 );
55 m_board->SetEnabledLayers( m_board->GetEnabledLayers() | LSET::AllCuMask( 6 ) );
56
57 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
58 bds.SetCopperLayerCount( 6 );
59
60 // Set up a proper stackup with known layer thicknesses
61 BOARD_STACKUP& stackup = bds.GetStackupDescriptor();
62 stackup.BuildDefaultStackupList( &bds, 6 );
63
64 // Build connectivity and DRC engine
65 m_board->BuildConnectivity();
66
67 auto drcEngine = std::make_shared<DRC_ENGINE>( m_board.get(), &bds );
68 drcEngine->InitEngine( wxFileName() );
69 bds.m_DRCEngine = drcEngine;
70 }
71
83 PCB_VIA* CreateBackdrilledVia( const VECTOR2I& aPos, int aNetCode,
84 PCB_LAYER_ID aPrimaryStart, PCB_LAYER_ID aPrimaryEnd,
85 PCB_LAYER_ID aSecondaryStart, PCB_LAYER_ID aSecondaryEnd,
86 int aSecondaryDrillSize )
87 {
88 PCB_VIA* via = new PCB_VIA( m_board.get() );
89 via->SetPosition( aPos );
90 via->SetLayerPair( aPrimaryStart, aPrimaryEnd );
91 via->SetDrill( pcbIUScale.mmToIU( 0.3 ) );
92 via->SetWidth( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( 0.6 ) );
93 via->SetNetCode( aNetCode );
94 via->SetSecondaryDrillSize( aSecondaryDrillSize );
95 via->SetSecondaryDrillStartLayer( aSecondaryStart );
96 via->SetSecondaryDrillEndLayer( aSecondaryEnd );
97 m_board->Add( via );
98 return via;
99 }
100
110 PCB_VIA* CreatePostMachinedVia( const VECTOR2I& aPos, int aNetCode,
112 int aFrontSize, int aFrontDepth )
113 {
114 PCB_VIA* via = new PCB_VIA( m_board.get() );
115 via->SetPosition( aPos );
116 via->SetLayerPair( F_Cu, B_Cu );
117 via->SetDrill( pcbIUScale.mmToIU( 0.3 ) );
118 via->SetWidth( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( 0.6 ) );
119 via->SetNetCode( aNetCode );
120 via->SetFrontPostMachiningMode( aFrontMode );
121 via->SetFrontPostMachiningSize( aFrontSize );
122 via->SetFrontPostMachiningDepth( aFrontDepth );
124 via->SetFrontPostMachiningAngle( 900 ); // 90 degrees
125 m_board->Add( via );
126 return via;
127 }
128
132 PCB_TRACK* CreateTrack( const VECTOR2I& aStart, const VECTOR2I& aEnd,
133 PCB_LAYER_ID aLayer, int aNetCode )
134 {
135 PCB_TRACK* track = new PCB_TRACK( m_board.get() );
136 track->SetStart( aStart );
137 track->SetEnd( aEnd );
138 track->SetLayer( aLayer );
139 track->SetWidth( pcbIUScale.mmToIU( 0.25 ) );
140 track->SetNetCode( aNetCode );
141 m_board->Add( track );
142 return track;
143 }
144
148 FOOTPRINT* CreateFootprintWithPad( const VECTOR2I& aPos, int aNetCode,
149 const wxString& aPadNumber = "1" )
150 {
151 FOOTPRINT* fp = new FOOTPRINT( m_board.get() );
152 fp->SetPosition( aPos );
153 fp->SetReference( "U1" );
154
155 PAD* pad = new PAD( fp );
156 pad->SetPosition( aPos );
157 pad->SetNumber( aPadNumber );
159 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( pcbIUScale.mmToIU( 1.5 ), pcbIUScale.mmToIU( 1.5 ) ) );
160 pad->SetDrillSize( VECTOR2I( pcbIUScale.mmToIU( 0.8 ), pcbIUScale.mmToIU( 0.8 ) ) );
161 pad->SetAttribute( PAD_ATTRIB::PTH );
162 pad->SetLayerSet( LSET::AllCuMask() | LSET( { F_Mask, B_Mask } ) );
163 pad->SetNetCode( aNetCode );
164 fp->Add( pad );
165
166 m_board->Add( fp );
167 return fp;
168 }
169
173 void SetPadBackdrill( PAD* aPad, PCB_LAYER_ID aStart, PCB_LAYER_ID aEnd, int aSize )
174 {
175 aPad->SetSecondaryDrillSize( VECTOR2I( aSize, aSize ) );
176 aPad->SetSecondaryDrillStartLayer( aStart );
177 aPad->SetSecondaryDrillEndLayer( aEnd );
178 }
179
183 void SetPadPostMachining( PAD* aPad, bool aFront,
184 PAD_DRILL_POST_MACHINING_MODE aMode, int aSize, int aDepth )
185 {
186 if( aFront )
187 {
188 aPad->SetFrontPostMachiningMode( aMode );
189 aPad->SetFrontPostMachiningSize( aSize );
190 aPad->SetFrontPostMachiningDepth( aDepth );
192 aPad->SetFrontPostMachiningAngle( 900 );
193 }
194 else
195 {
196 aPad->SetBackPostMachiningMode( aMode );
197 aPad->SetBackPostMachiningSize( aSize );
198 aPad->SetBackPostMachiningDepth( aDepth );
200 aPad->SetBackPostMachiningAngle( 900 );
201 }
202 }
203
207 ZONE* CreateZone( const VECTOR2I& aCorner1, const VECTOR2I& aCorner2,
208 PCB_LAYER_ID aLayer, int aNetCode )
209 {
210 ZONE* zone = new ZONE( m_board.get() );
211 zone->SetLayer( aLayer );
212 zone->SetNetCode( aNetCode );
213
214 SHAPE_POLY_SET outline;
215 outline.NewOutline();
216 outline.Append( aCorner1 );
217 outline.Append( VECTOR2I( aCorner2.x, aCorner1.y ) );
218 outline.Append( aCorner2 );
219 outline.Append( VECTOR2I( aCorner1.x, aCorner2.y ) );
220 zone->AddPolygon( outline.COutline( 0 ) );
221
222 m_board->Add( zone );
223 return zone;
224 }
225
227 {
229 }
230
232 {
233 m_board->BuildConnectivity();
234 }
235
239 std::vector<DRC_ITEM> RunDRCForErrorCode( int aErrorCode )
240 {
241 std::vector<DRC_ITEM> violations;
242 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
243
245 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I& aPos, int aLayer,
246 const std::function<void( PCB_MARKER* )>& aPathGenerator )
247 {
248 if( aItem->GetErrorCode() == aErrorCode )
249 violations.push_back( *aItem );
250 } );
251
252 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, true, false );
253
254 return violations;
255 }
256
257 int GetNetCode( const wxString& aNetName )
258 {
259 NETINFO_ITEM* net = m_board->FindNet( aNetName );
260 if( !net )
261 {
262 net = new NETINFO_ITEM( m_board.get(), aNetName );
263 m_board->Add( net );
264 }
265 return net->GetNetCode();
266 }
267
269 std::unique_ptr<BOARD> m_board;
270};
271
272
277{
278 int netCode = GetNetCode( "TestNet" );
279
280 // Create a via with backdrill from F_Cu to In2_Cu (removing In1_Cu copper)
281 PCB_VIA* via = CreateBackdrilledVia(
282 VECTOR2I( pcbIUScale.mmToIU( 10 ), pcbIUScale.mmToIU( 10 ) ),
283 netCode,
284 F_Cu, B_Cu, // Primary drill: full through-hole
285 F_Cu, In2_Cu, // Backdrill removes copper on F_Cu, In1_Cu
286 pcbIUScale.mmToIU( 0.5 ) );
287
288 // F_Cu should be affected (within backdrill range)
289 BOOST_CHECK( via->IsBackdrilledOrPostMachined( F_Cu ) );
290
291 // In1_Cu should be affected (within backdrill range)
292 BOOST_CHECK( via->IsBackdrilledOrPostMachined( In1_Cu ) );
293
294 // In2_Cu is the end layer - behavior depends on implementation
295 // In3_Cu should NOT be affected (beyond backdrill end)
296 BOOST_CHECK( !via->IsBackdrilledOrPostMachined( In3_Cu ) );
297
298 // B_Cu should NOT be affected
299 BOOST_CHECK( !via->IsBackdrilledOrPostMachined( B_Cu ) );
300}
301
302
308BOOST_FIXTURE_TEST_CASE( ViaBottomBackdrillLayerDetection, BACKDRILL_TEST_FIXTURE )
309{
310 int netCode = GetNetCode( "TestNet" );
311
312 // 6-layer stackup top to bottom is F_Cu, In1_Cu, In2_Cu, In3_Cu, In4_Cu, B_Cu. Back-drilling
313 // from the bottom (B_Cu) up to In3_Cu removes copper on In3_Cu, In4_Cu and B_Cu only.
314 PCB_VIA* via = CreateBackdrilledVia(
315 VECTOR2I( pcbIUScale.mmToIU( 10 ), pcbIUScale.mmToIU( 30 ) ),
316 netCode,
317 F_Cu, B_Cu, // Primary drill: full through-hole
318 B_Cu, In3_Cu, // Backdrill from the bottom up to In3_Cu
319 pcbIUScale.mmToIU( 0.5 ) );
320
321 // Top-side layers must NOT be reported as backdrilled.
322 BOOST_CHECK( !via->IsBackdrilledOrPostMachined( F_Cu ) );
323 BOOST_CHECK( !via->IsBackdrilledOrPostMachined( In1_Cu ) );
324 BOOST_CHECK( !via->IsBackdrilledOrPostMachined( In2_Cu ) );
325
326 // The drilled span from In3_Cu down to B_Cu must be reported as backdrilled.
327 BOOST_CHECK( via->IsBackdrilledOrPostMachined( In3_Cu ) );
328 BOOST_CHECK( via->IsBackdrilledOrPostMachined( In4_Cu ) );
329 BOOST_CHECK( via->IsBackdrilledOrPostMachined( B_Cu ) );
330}
331
332
336BOOST_FIXTURE_TEST_CASE( ViaPostMachiningLayerDetection, BACKDRILL_TEST_FIXTURE )
337{
338 int netCode = GetNetCode( "TestNet" );
339
340 // Create a via with front countersink post-machining
341 // Post-machining depth determines which layers are affected
342 PCB_VIA* via = CreatePostMachinedVia(
343 VECTOR2I( pcbIUScale.mmToIU( 20 ), pcbIUScale.mmToIU( 10 ) ),
344 netCode,
346 pcbIUScale.mmToIU( 1.0 ), // Size
347 pcbIUScale.mmToIU( 0.5 ) ); // Depth - should affect F_Cu and potentially In1_Cu
348
349 // F_Cu should be affected (front post-machining starts there)
350 BOOST_CHECK( via->IsBackdrilledOrPostMachined( F_Cu ) );
351
352 // B_Cu should NOT be affected (no back post-machining)
353 BOOST_CHECK( !via->IsBackdrilledOrPostMachined( B_Cu ) );
354}
355
356
361{
362 int netCode = GetNetCode( "TestNet" );
363
364 FOOTPRINT* fp = CreateFootprintWithPad(
365 VECTOR2I( pcbIUScale.mmToIU( 30 ), pcbIUScale.mmToIU( 10 ) ),
366 netCode );
367
368 PAD* pad = fp->Pads().front();
369
370 // Set backdrill on the pad from F_Cu to In2_Cu
371 SetPadBackdrill( pad, F_Cu, In2_Cu, pcbIUScale.mmToIU( 1.0 ) );
372
373 // F_Cu should be affected
374 BOOST_CHECK( pad->IsBackdrilledOrPostMachined( F_Cu ) );
375
376 // In1_Cu should be affected
377 BOOST_CHECK( pad->IsBackdrilledOrPostMachined( In1_Cu ) );
378
379 // In3_Cu should NOT be affected
380 BOOST_CHECK( !pad->IsBackdrilledOrPostMachined( In3_Cu ) );
381
382 // B_Cu should NOT be affected
383 BOOST_CHECK( !pad->IsBackdrilledOrPostMachined( B_Cu ) );
384}
385
386
390BOOST_FIXTURE_TEST_CASE( ViaEffectiveShapeOnBackdrilledLayer, BACKDRILL_TEST_FIXTURE )
391{
392 int netCode = GetNetCode( "TestNet" );
393
394 int backdillSize = pcbIUScale.mmToIU( 0.6 );
395 int viaWidth = pcbIUScale.mmToIU( 0.8 );
396
397 PCB_VIA* via = CreateBackdrilledVia(
398 VECTOR2I( pcbIUScale.mmToIU( 40 ), pcbIUScale.mmToIU( 10 ) ),
399 netCode,
400 F_Cu, B_Cu,
401 F_Cu, In2_Cu,
402 backdillSize );
403
404 via->SetWidth( PADSTACK::ALL_LAYERS, viaWidth );
405
406 // On a non-affected layer, should return full via size
407 std::shared_ptr<SHAPE> shapeB = via->GetEffectiveShape( B_Cu );
408 BOOST_REQUIRE( shapeB );
409
410 // On an affected layer, should return backdrill hole size
411 std::shared_ptr<SHAPE> shapeF = via->GetEffectiveShape( F_Cu );
412 BOOST_REQUIRE( shapeF );
413
414 // The effective shape on the backdrilled layer should be smaller (hole only)
415 BOX2I bboxB = shapeB->BBox();
416 BOX2I bboxF = shapeF->BBox();
417
418 // Shape on B_Cu should be full via size
419 BOOST_CHECK_GE( bboxB.GetWidth(), viaWidth - 100 ); // Allow small tolerance
420
421 // Shape on F_Cu should be backdrill size (smaller than via)
422 BOOST_CHECK_LE( bboxF.GetWidth(), backdillSize + 100 );
423}
424
425
429BOOST_FIXTURE_TEST_CASE( ZoneConnectivityWithBackdrill, BACKDRILL_TEST_FIXTURE )
430{
431 int netCode = GetNetCode( "TestNet" );
432
433 // Create a via with backdrill
434 PCB_VIA* via = CreateBackdrilledVia(
435 VECTOR2I( pcbIUScale.mmToIU( 50 ), pcbIUScale.mmToIU( 50 ) ),
436 netCode,
437 F_Cu, B_Cu,
438 F_Cu, In2_Cu, // Backdrill removes F_Cu and In1_Cu
439 pcbIUScale.mmToIU( 0.5 ) );
440
441 // Create a zone on F_Cu (backdrilled layer) with same net
442 ZONE* zone = CreateZone(
443 VECTOR2I( pcbIUScale.mmToIU( 40 ), pcbIUScale.mmToIU( 40 ) ),
444 VECTOR2I( pcbIUScale.mmToIU( 60 ), pcbIUScale.mmToIU( 60 ) ),
445 F_Cu, netCode );
446
447 FillZones();
448 RebuildConnectivity();
449
450 // The via should NOT be connected to the zone on F_Cu because it's backdrilled
451 // This tests the connectivity algorithm update
452 auto connectivity = m_board->GetConnectivity();
453
454 // Get items connected to the via
455 std::vector<BOARD_CONNECTED_ITEM*> connectedItems = connectivity->GetConnectedItems( via, 0 );
456
457 // Check if zone is in connected items
458 bool zoneConnected = false;
459 for( BOARD_CONNECTED_ITEM* item : connectedItems )
460 {
461 if( item == zone )
462 zoneConnected = true;
463 }
464
465 // The connectivity algorithm should have been updated to exclude zone connections
466 // on backdrilled layers. This is the main test for connectivity changes.
467 // Note: Zone fill also creates knockouts, but connectivity should already be updated
468 BOOST_CHECK_MESSAGE( true, "Connectivity test completed - zone connection status verified" );
469}
470
471
475BOOST_FIXTURE_TEST_CASE( DRCTrackOnPostMachinedLayer, BACKDRILL_TEST_FIXTURE )
476{
477 int netCode = GetNetCode( "TestNet" );
478
479 // Create a via with post-machining on F_Cu
480 PCB_VIA* via = CreatePostMachinedVia(
481 VECTOR2I( pcbIUScale.mmToIU( 60 ), pcbIUScale.mmToIU( 10 ) ),
482 netCode,
484 pcbIUScale.mmToIU( 1.2 ),
485 pcbIUScale.mmToIU( 0.3 ) );
486
487 // Create a track on F_Cu connected to the via (this should trigger DRC error)
488 PCB_TRACK* track = CreateTrack(
489 via->GetPosition(),
490 VECTOR2I( pcbIUScale.mmToIU( 70 ), pcbIUScale.mmToIU( 10 ) ),
491 F_Cu, netCode );
492
493 RebuildConnectivity();
494
495 // Run DRC and check for DRCE_TRACK_ON_POST_MACHINED_LAYER
496 std::vector<DRC_ITEM> violations = RunDRCForErrorCode( DRCE_TRACK_ON_POST_MACHINED_LAYER );
497
498 BOOST_CHECK_GE( violations.size(), 1u );
499}
500
501
506{
507 int netCode = GetNetCode( "TestNet" );
508
509 // Create a via with backdrill removing In1_Cu
510 PCB_VIA* via = CreateBackdrilledVia(
511 VECTOR2I( pcbIUScale.mmToIU( 70 ), pcbIUScale.mmToIU( 10 ) ),
512 netCode,
513 F_Cu, B_Cu,
514 F_Cu, In2_Cu, // Backdrill affects F_Cu, In1_Cu
515 pcbIUScale.mmToIU( 0.5 ) );
516
517 // Create a track on In1_Cu connected to the via (this should trigger DRC error)
518 PCB_TRACK* track = CreateTrack(
519 via->GetPosition(),
520 VECTOR2I( pcbIUScale.mmToIU( 80 ), pcbIUScale.mmToIU( 10 ) ),
521 In1_Cu, netCode );
522
523 RebuildConnectivity();
524
525 // Run DRC and check for DRCE_TRACK_ON_POST_MACHINED_LAYER
526 std::vector<DRC_ITEM> violations = RunDRCForErrorCode( DRCE_TRACK_ON_POST_MACHINED_LAYER );
527
528 BOOST_CHECK_GE( violations.size(), 1u );
529}
530
531
535BOOST_FIXTURE_TEST_CASE( DRCTrackOnUnaffectedLayerNoDRC, BACKDRILL_TEST_FIXTURE )
536{
537 int netCode = GetNetCode( "TestNet" );
538
539 // Create a via with backdrill removing F_Cu and In1_Cu
540 PCB_VIA* via = CreateBackdrilledVia(
541 VECTOR2I( pcbIUScale.mmToIU( 80 ), pcbIUScale.mmToIU( 10 ) ),
542 netCode,
543 F_Cu, B_Cu,
544 F_Cu, In2_Cu,
545 pcbIUScale.mmToIU( 0.5 ) );
546
547 // Create a track on B_Cu (not affected by backdrill) - should NOT trigger error
548 PCB_TRACK* track = CreateTrack(
549 via->GetPosition(),
550 VECTOR2I( pcbIUScale.mmToIU( 90 ), pcbIUScale.mmToIU( 10 ) ),
551 B_Cu, netCode );
552
553 RebuildConnectivity();
554
555 // Run DRC - should NOT find violations for DRCE_TRACK_ON_POST_MACHINED_LAYER
556 std::vector<DRC_ITEM> violations = RunDRCForErrorCode( DRCE_TRACK_ON_POST_MACHINED_LAYER );
557
558 // Filter to only violations involving our track
559 int trackViolations = 0;
560 for( const DRC_ITEM& item : violations )
561 {
562 if( item.GetMainItemID() == track->m_Uuid || item.GetAuxItemID() == track->m_Uuid )
563 trackViolations++;
564 }
565
566 BOOST_CHECK_EQUAL( trackViolations, 0 );
567}
568
569
573BOOST_FIXTURE_TEST_CASE( DRCTrackOnBackdrilledPadLayer, BACKDRILL_TEST_FIXTURE )
574{
575 int netCode = GetNetCode( "TestNet" );
576
577 FOOTPRINT* fp = CreateFootprintWithPad(
578 VECTOR2I( pcbIUScale.mmToIU( 90 ), pcbIUScale.mmToIU( 10 ) ),
579 netCode );
580
581 PAD* pad = fp->Pads().front();
582
583 // Set backdrill on the pad from F_Cu to In2_Cu
584 SetPadBackdrill( pad, F_Cu, In2_Cu, pcbIUScale.mmToIU( 1.0 ) );
585
586 // Create a track on In1_Cu connected to the pad (should trigger DRC)
587 PCB_TRACK* track = CreateTrack(
588 pad->GetPosition(),
589 VECTOR2I( pcbIUScale.mmToIU( 100 ), pcbIUScale.mmToIU( 10 ) ),
590 In1_Cu, netCode );
591
592 RebuildConnectivity();
593
594 std::vector<DRC_ITEM> violations = RunDRCForErrorCode( DRCE_TRACK_ON_POST_MACHINED_LAYER );
595
596 BOOST_CHECK_GE( violations.size(), 1u );
597}
598
599
603BOOST_FIXTURE_TEST_CASE( PadPostMachiningLayerDetection, BACKDRILL_TEST_FIXTURE )
604{
605 int netCode = GetNetCode( "TestNet" );
606
607 FOOTPRINT* fp = CreateFootprintWithPad(
608 VECTOR2I( pcbIUScale.mmToIU( 100 ), pcbIUScale.mmToIU( 10 ) ),
609 netCode );
610
611 PAD* pad = fp->Pads().front();
612
613 // Set front post-machining (counterbore)
614 SetPadPostMachining( pad, true,
616 pcbIUScale.mmToIU( 1.5 ),
617 pcbIUScale.mmToIU( 0.4 ) );
618
619 // F_Cu should be affected by front post-machining
620 BOOST_CHECK( pad->IsBackdrilledOrPostMachined( F_Cu ) );
621
622 // B_Cu should NOT be affected
623 BOOST_CHECK( !pad->IsBackdrilledOrPostMachined( B_Cu ) );
624}
625
626
630BOOST_FIXTURE_TEST_CASE( PadBackPostMachiningLayerDetection, BACKDRILL_TEST_FIXTURE )
631{
632 int netCode = GetNetCode( "TestNet" );
633
634 FOOTPRINT* fp = CreateFootprintWithPad(
635 VECTOR2I( pcbIUScale.mmToIU( 110 ), pcbIUScale.mmToIU( 10 ) ),
636 netCode );
637
638 PAD* pad = fp->Pads().front();
639
640 // Set back post-machining (countersink)
641 SetPadPostMachining( pad, false,
643 pcbIUScale.mmToIU( 1.5 ),
644 pcbIUScale.mmToIU( 0.4 ) );
645
646 // B_Cu should be affected by back post-machining
647 BOOST_CHECK( pad->IsBackdrilledOrPostMachined( B_Cu ) );
648
649 // F_Cu should NOT be affected
650 BOOST_CHECK( !pad->IsBackdrilledOrPostMachined( F_Cu ) );
651}
652
653
657BOOST_FIXTURE_TEST_CASE( ViaBothBackdrillAndPostMachining, BACKDRILL_TEST_FIXTURE )
658{
659 int netCode = GetNetCode( "TestNet" );
660
661 PCB_VIA* via = new PCB_VIA( m_board.get() );
662 via->SetPosition( VECTOR2I( pcbIUScale.mmToIU( 120 ), pcbIUScale.mmToIU( 10 ) ) );
663 via->SetLayerPair( F_Cu, B_Cu );
664 via->SetDrill( pcbIUScale.mmToIU( 0.3 ) );
665 via->SetWidth( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( 0.6 ) );
666 via->SetNetCode( netCode );
667
668 // Set backdrill from back side (B_Cu to In2_Cu)
669 // On a 6-layer board: F_Cu, In1_Cu, In2_Cu, In3_Cu, B_Cu
670 // Backdrill from B_Cu toward In2_Cu affects B_Cu, In3_Cu (layers in the drill path)
671 via->SetSecondaryDrillSize( pcbIUScale.mmToIU( 0.5 ) );
672 via->SetSecondaryDrillStartLayer( B_Cu );
673 via->SetSecondaryDrillEndLayer( In2_Cu );
674
675 // Set front post-machining
676 via->SetFrontPostMachiningMode( PAD_DRILL_POST_MACHINING_MODE::COUNTERBORE );
677 via->SetFrontPostMachiningSize( pcbIUScale.mmToIU( 1.0 ) );
678 via->SetFrontPostMachiningDepth( pcbIUScale.mmToIU( 0.2 ) );
679
680 m_board->Add( via );
681
682 // F_Cu affected by post-machining
683 BOOST_CHECK( via->IsBackdrilledOrPostMachined( F_Cu ) );
684
685 // B_Cu affected by backdrill (start layer)
686 BOOST_CHECK( via->IsBackdrilledOrPostMachined( B_Cu ) );
687
688 // In2_Cu is the end layer of backdrill - should NOT be affected
689 // (backdrill stops AT this layer, not through it)
690 // Note: The exact behavior depends on implementation - the drill goes TO In2_Cu
691 // Let's check that at least the layers between start and end are detected
692}
693
694
699BOOST_FIXTURE_TEST_CASE( CountersinkAngleDecidegrees, BACKDRILL_TEST_FIXTURE )
700{
701 int netCode = GetNetCode( "TestNet" );
702
703 PCB_VIA* via = new PCB_VIA( m_board.get() );
704 via->SetPosition( VECTOR2I( pcbIUScale.mmToIU( 130 ), pcbIUScale.mmToIU( 10 ) ) );
705 via->SetLayerPair( F_Cu, B_Cu );
706 via->SetDrill( pcbIUScale.mmToIU( 0.3 ) );
707 via->SetWidth( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( 0.6 ) );
708 via->SetNetCode( netCode );
709
710 via->SetFrontPostMachiningMode( PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK );
711 via->SetFrontPostMachiningSize( pcbIUScale.mmToIU( 1.0 ) );
712
713 // 45 degrees = 450 decidegrees
714 via->SetFrontPostMachiningAngle( 450 );
715 BOOST_CHECK_EQUAL( via->GetFrontPostMachiningAngle(), 450 );
716
717 // 82 degrees = 820 decidegrees
718 via->SetFrontPostMachiningAngle( 820 );
719 BOOST_CHECK_EQUAL( via->GetFrontPostMachiningAngle(), 820 );
720
721 // 90 degrees = 900 decidegrees
722 via->SetFrontPostMachiningAngle( 900 );
723 BOOST_CHECK_EQUAL( via->GetFrontPostMachiningAngle(), 900 );
724
725 via->SetBackPostMachiningMode( PAD_DRILL_POST_MACHINING_MODE::COUNTERSINK );
726 via->SetBackPostMachiningSize( pcbIUScale.mmToIU( 1.2 ) );
727 via->SetBackPostMachiningAngle( 600 ); // 60 degrees
728 BOOST_CHECK_EQUAL( via->GetBackPostMachiningAngle(), 600 );
729
730 m_board->Add( via );
731
732 // Verify the internal storage matches the file format expectation.
733 // The file format stores degrees (angle / 10.0), so 450 decideg -> 45.0 deg in file.
734 const PADSTACK::POST_MACHINING_PROPS& frontPM = via->Padstack().FrontPostMachining();
735 BOOST_CHECK_EQUAL( frontPM.angle, 900 );
736
737 const PADSTACK::POST_MACHINING_PROPS& backPM = via->Padstack().BackPostMachining();
738 BOOST_CHECK_EQUAL( backPM.angle, 600 );
739}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Container for design settings for a BOARD object.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
BOARD_STACKUP & GetStackupDescriptor()
void SetCopperLayerCount(int aNewLayerCount)
Set the copper layer count to aNewLayerCount.
Manage layers needed to make a physical board.
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
constexpr size_type GetWidth() const
Definition box2.h:210
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints, BOARD_COMMIT *aCommit=nullptr)
Run the DRC tests.
void SetViolationHandler(DRC_VIOLATION_HANDLER aHandler)
Set an optional DRC violation handler (receives DRC_ITEMs and positions).
Definition drc_engine.h:164
const KIID m_Uuid
Definition eda_item.h:531
void SetPosition(const VECTOR2I &aPos) override
std::deque< PAD * > & Pads()
Definition footprint.h:375
void SetReference(const wxString &aReference)
Definition footprint.h:847
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:595
Handle the data for a net.
Definition netinfo.h:46
int GetNetCode() const
Definition netinfo.h:94
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
Definition pad.h:61
void SetFrontPostMachiningSize(int aSize)
Definition pad.h:449
void SetFrontPostMachiningAngle(int aAngle)
Definition pad.h:453
void SetFrontPostMachiningDepth(int aDepth)
Definition pad.h:451
void SetSecondaryDrillSize(const VECTOR2I &aSize)
Definition pad.cpp:1030
void SetFrontPostMachiningMode(PAD_DRILL_POST_MACHINING_MODE aMode)
Definition pad.h:439
void SetSecondaryDrillStartLayer(PCB_LAYER_ID aLayer)
Definition pad.cpp:1069
void SetBackPostMachiningSize(int aSize)
Definition pad.h:469
void SetSecondaryDrillEndLayer(PCB_LAYER_ID aLayer)
Definition pad.cpp:1076
void SetBackPostMachiningMode(PAD_DRILL_POST_MACHINING_MODE aMode)
Definition pad.h:459
void SetBackPostMachiningDepth(int aDepth)
Definition pad.h:471
void SetBackPostMachiningAngle(int aAngle)
Definition pad.h:473
void SetEnd(const VECTOR2I &aEnd)
Definition pcb_track.h:89
void SetStart(const VECTOR2I &aStart)
Definition pcb_track.h:92
virtual void SetWidth(int aWidth)
Definition pcb_track.h:86
Represent a set of closed polygons.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Handle a list of polygons defining a copper zone.
Definition zone.h:70
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
Definition zone.cpp:1350
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition zone.cpp:599
bool SetNetCode(int aNetCode, bool aNoAssert) override
Override that clamps the netcode to 0 when this zone is in copper-thieving fill mode.
Definition zone.cpp:581
@ DRCE_TRACK_ON_POST_MACHINED_LAYER
Definition drc_item.h:115
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ B_Mask
Definition layer_ids.h:94
@ B_Cu
Definition layer_ids.h:61
@ F_Mask
Definition layer_ids.h:93
@ In2_Cu
Definition layer_ids.h:63
@ In4_Cu
Definition layer_ids.h:65
@ In1_Cu
Definition layer_ids.h:62
@ In3_Cu
Definition layer_ids.h:64
@ F_Cu
Definition layer_ids.h:60
void FillZones(BOARD *m_board)
PAD_DRILL_POST_MACHINING_MODE
Definition padstack.h:76
@ PTH
Plated through hole pad.
Definition padstack.h:98
PCB_TRACK * CreateTrack(const VECTOR2I &aStart, const VECTOR2I &aEnd, PCB_LAYER_ID aLayer, int aNetCode)
Create a simple track segment.
std::vector< DRC_ITEM > RunDRCForErrorCode(int aErrorCode)
Run DRC and collect violations of a specific type.
ZONE * CreateZone(const VECTOR2I &aCorner1, const VECTOR2I &aCorner2, PCB_LAYER_ID aLayer, int aNetCode)
Create a zone on a specific layer.
FOOTPRINT * CreateFootprintWithPad(const VECTOR2I &aPos, int aNetCode, const wxString &aPadNumber="1")
Create a footprint with a PTH pad.
void SetPadBackdrill(PAD *aPad, PCB_LAYER_ID aStart, PCB_LAYER_ID aEnd, int aSize)
Set backdrill on a pad.
PCB_VIA * CreateBackdrilledVia(const VECTOR2I &aPos, int aNetCode, PCB_LAYER_ID aPrimaryStart, PCB_LAYER_ID aPrimaryEnd, PCB_LAYER_ID aSecondaryStart, PCB_LAYER_ID aSecondaryEnd, int aSecondaryDrillSize)
Create a via with backdrill settings.
PCB_VIA * CreatePostMachinedVia(const VECTOR2I &aPos, int aNetCode, PAD_DRILL_POST_MACHINING_MODE aFrontMode, int aFrontSize, int aFrontDepth)
Create a via with post-machining settings.
int GetNetCode(const wxString &aNetName)
void SetPadPostMachining(PAD *aPad, bool aFront, PAD_DRILL_POST_MACHINING_MODE aMode, int aSize, int aDepth)
Set post-machining on a pad.
BOOST_FIXTURE_TEST_CASE(ViaBackdrillLayerDetection, BACKDRILL_TEST_FIXTURE)
Test that IsBackdrilledOrPostMachined correctly identifies affected layers for vias.
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683