Attached is a patch that I wrote that gives PCB the ability to generate non 100% paste filled areas on selected pads. (screenshot of generated pads with 50% coverage also attached)

The patch specifies a minimum "solder paste island" size and then proceeds to calculate the number and size of the solder paste islands required achieve the desired coverage. I have tested the code a bit, but there could of course be some hidden bugs in there. If it matters, I use the GTK hid (lesstiff not tested).

This particular patch has a couple of flaws in that I hard coded the percent solder paste coverage and the minimum island size in the file, and also that I used/abused the "nopaste" flag to mark pads that want the island treatment. I did the latter because I don't yet understand all of the nuances of adding a new flag(s) to the PCB file.

To use the patch:
Apply to draw.c
Build.
Open a PCB layout.
Select the pad to which you want apply reduced solder paste coverage.
Use the :ChangePaste(Selected) command to set the "nopaste" flag.
You can verify the above operation with the "Ctrl-R" report command on the pad--- look for the "no paste" flag. Export the gerber files --- you should see the solder islands on the paste layer.

Cheers,
David Carr (celebrating 23 years today)


David Carr wrote:
I have the distinct (dis)pleasure of making some PCBs with QFN/MLF packages
that have exposed copper paddles.  I think I'll need to use stencils to
properly apply paste for these packages.  It appears that PCB simply uses
SMT pads (slightly shrunk) as the apertures for the paste layer.  I think
this is a simple effective design for most packages --- except exposed
ground paddles.  These require that the paste be broken into smaller
"blocks" with say 75% coverage of the paddle.  (See Analog AN-772)

Has anyone on the list dealt with this issue in the past?  If not, I wonder
if there is any way to distinguish paddle pads from regular ones so that I
could modify the paste layer code to do the right thing.  I guess we could
do something like look for square pads with a size > Xmm on a side.  That
seems a big fragile though.

Hmmm,
-DC



_______________________________________________
geda-dev mailing list
[email protected]
http://www.seul.org/cgi-bin/mailman/listinfo/geda-dev

--- /tmp/pcb-20080202/src/draw.c	2007-12-11 08:00:05.000000000 -0600
+++ pcb-paddlepaste/src/draw.c	2008-02-07 17:18:13.000000000 -0600
@@ -98,6 +98,7 @@
 static void DrawPinOrViaNameLowLevel (PinTypePtr);
 static void DrawPadLowLevel (hidGC, PadTypePtr, Boolean, Boolean);
 static void DrawPadNameLowLevel (PadTypePtr);
+static void DrawPaddlePaste (hidGC, PadTypePtr);
 static void DrawLineLowLevel (LineTypePtr, Boolean);
 static void DrawRegularText (LayerTypePtr, TextTypePtr, int);
 static void DrawPolygonLowLevel (PolygonTypePtr);
@@ -567,8 +568,13 @@
 	    if ((TEST_FLAG (ONSOLDERFLAG, pad) && side == SOLDER_LAYER)
 		|| (!TEST_FLAG (ONSOLDERFLAG, pad)
 		    && side == COMPONENT_LAYER))
+	    {
 	      if (!TEST_FLAG (NOPASTEFLAG, pad))
 		DrawPadLowLevel (Output.fgGC, pad, False, False);
+	      //david mod
+              else //NOPASTEFLAG is set
+                 DrawPaddlePaste(Output.fgGC, pad);
+            }
 	  }
 	  ENDALL_LOOP;
 	}
@@ -1354,6 +1360,7 @@
       return;
     }
 
+  //Thin draw pads
   if (TEST_FLAG (THINDRAWFLAG, PCB) ||
       (clear && TEST_FLAG (THINDRAWPOLYFLAG, PCB)))
     {
@@ -1447,6 +1454,7 @@
 	    }
 	}
     }
+  //zero length pads
   else if (Pad->Point1.X == Pad->Point2.X
            && Pad->Point1.Y == Pad->Point2.Y)
     {
@@ -1464,6 +1472,7 @@
           gui->fill_circle (gc, Pad->Point1.X, Pad->Point1.Y, w / 2);
         }
     }
+  //other pads (normal?)
   else
     {
       gui->set_line_cap (gc,
@@ -1548,6 +1557,60 @@
 
 }
 
+/* --------------------------------------------------------------------------
+ * draws paste patterns for exposed paddles
+ */
+static void DrawPaddlePaste(hidGC gc, PadTypePtr Pad)
+{
+  /*
+   * Quick note about variables:
+   * - Paddle* refers to the size of the exposed paddle land
+   * - We fill this area with 1+ islands of solder paste
+   * - These islands have dimensions IslandWidth x IslandHeight
+   * - They are spaced on horizontal and vertical pitches specified by
+   * IslandPitchH and IslandPitchV respectively
+   */
+      
+  float FillFraction = 0.5;  //50% of the paddle is coverted with paste
+  int MinIslandSize = 3000; //30 mils
+  int MinIslandPitch = (1.0/sqrt(FillFraction)) * MinIslandSize;
+
+  int PaddleWidth = abs(Pad->Point2.X - Pad->Point1.X) + Pad->Thickness;
+  int PaddleHeight = abs(Pad->Point2.Y - Pad->Point1.Y) + Pad->Thickness;
+
+  //cordinates of upper left corner of paddle
+  int PaddleULX = 0.5*(Pad->Point1.X + Pad->Point2.X) - 0.5*PaddleWidth;
+  int PaddleULY = 0.5*(Pad->Point1.Y + Pad->Point2.Y) - 0.5*PaddleHeight;
+
+  int IslandsAcross = max(1, floor(PaddleWidth/MinIslandPitch));
+  int IslandsHigh = max(1, floor(PaddleHeight/MinIslandPitch));
+
+  int IslandPitchH = PaddleWidth/IslandsAcross;
+  int IslandPitchV = PaddleHeight/IslandsHigh;
+
+  int IslandWidth = IslandPitchH * sqrt(FillFraction);
+  int IslandHeight = IslandPitchV * sqrt(FillFraction);
+
+  //We'll offset the position of the islands right and down by half
+  //width of the gap between islands
+  int OffsetH = 0.5*(IslandPitchH - IslandWidth) + PaddleULX;
+  int OffsetV = 0.5*(IslandPitchV - IslandHeight) + PaddleULY;
+
+  int x;
+  int y;
+  //Draw all of the islands
+  for (x=0; x<IslandsAcross; x++)
+   for (y=0; y<IslandsHigh; y++)
+    {
+	int l = OffsetH + x*IslandPitchH;
+	int b = OffsetV + y*IslandPitchV + IslandHeight;
+	int r = OffsetH + x*IslandPitchH + IslandWidth;
+	int t = OffsetV + y*IslandPitchV;
+
+	gui->fill_rect (gc, l, b, r, t);	 
+    }
+}
+
 /* ---------------------------------------------------------------------------
  * clearance for pads
  */

<<inline: Screenshot.png>>


_______________________________________________
geda-dev mailing list
[email protected]
http://www.seul.org/cgi-bin/mailman/listinfo/geda-dev

Reply via email to