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
