PCB Footprint Scripting Library

I have written a Guile Scheme library to help create gschem footprints using Guile as a scripting language. It depends on the general Guile Scheme library I have written.

You can browse the sources here, specifically the files that start with the word pads.

You can download the source code from the table of attachments below.

At the moment it remains undocumented.

Table of Contents

Installation

To install the Guile modules:

  1. Download the source code from the table of attachments below.
  2. Untar the distribution file; e.g.:
    • tar -xzf octw-guile-geda-modules-1.0.tar.gz
  3. Edit the Makefile:
    • Change the INSTALL_DIR to point to the directory in which you would like to install the modules.
  4. Run make to install the modules.

Example Uses

Just to give you a flavor of what the library does I'll give a few examples.

Snippet From the QFP Script

Here is a snippet from the Guile script I use to generate "Quad Flat Package" footprints:

  ;; Extract parameter values.
  (let-nth ((description (nth parameters))
            (lead-count (string->number (nth parameters)))
            (lead-width (evaled-string->cmil options (nth parameters)))
            (lead-length (evaled-string->cmil options (nth parameters)))
            (lead-offset (evaled-string->cmil options (nth parameters)))
            (component-width (evaled-string->cmil options (nth parameters)))
            (body-width (evaled-string->cmil options (nth parameters))))
    ;; Calculate derived values.  Assumes each side has the same number
    ;; of leads.
    (let ((x-offset (- (/ component-width 2) (/ lead-length 2)))
          (side-lead-count (/ lead-count 4)))
      ;; Build the pads and the silk outline.
      (let ((pads (compose-chain (r)
                    ;; Create one pad the dimensions of the lead, centered
                    ;; on the origin and aligned along the x-axis.
                    (make-pad-x lead-length lead-width
                                #:mask-extent *mask-extent*
                                #:clearance-extent *clearance-extent*)
                    ;; Grow its length and width for soldering.
                    (grow r extra-length extra-width)
                    ;; Move the pad to the left side of the component.
                    (move-along-x r (- x-offset))
                    ;; Generate the entire left row using the lead
                    ;; offset for spacing in the y direction, and using
                    ;; the original pad as the template for the new row
                    ;; pads.
                    (row r side-lead-count 0 lead-offset)
                    ;; Use the entire left row and rotated versions of
                    ;; it to create the three remaining rows.
                    (combine r
                             (rotate r 90)
                             (rotate r 180)
                             (rotate r 270))
                    ;; Number the pads.
                    (enumerate* r 1)))
            (silk (make-notched-outline-ul body-width
                                           body-width
                                           notch-length
                                           *silk-thickness*)))
        ;; Create the footprint by combining the pads and the silk.
        (let ((elem (make <element>
                      #:description description
                      #:name "U?"
                      #:contents (combine pads silk))))
          ;; Output the footprint.
          (output elem #t)))))

Building on Primitives

Here's an example of how you can build on the more primitive library functions and macros to generate higher level footprint components. These two functions generate a silk symbol for a slotted screw and a Phillips screw:

  (define (slotted-screw diameter angle thickness)
    ;; Create a circle of the given diameter and a slot.
    (let ((circle (make-element-circle (/ diameter 2) thickness))
          (slot (make-element-line diameter thickness
                                   (angle->unit-vector angle))))
      ;; Combine the circle and the slot.
      (combine circle slot)))

  (define (phillips-screw diameter angle thickness)
    ;; Create a circle of the given diameter and a single line of the
    ;; cross.
    (let ((circle (make-element-circle (/ diameter 2) thickness))
          (partial-cross (make-element-line (* 0.7 diameter) thickness
                                            (angle->unit-vector angle))))
      ;; Complete the cross by combining the partial cross and the
      ;; partial cross rotated through 90 degrees to complete the cross.
      (let ((cross (combine partial-cross (rotate partial-cross 90))))
        ;; Combine the circle and the cross.
        (combine circle cross)))
Further, these can be written a tad more succinctly like so:
  (define (slotted-screw diameter angle thickness)
    (combine (make-element-circle (/ diameter 2) thickness)
             (make-element-line diameter thickness
                                (angle->unit-vector angle))))

  (define (phillips-screw diameter angle thickness)
    (compose-chain (c)
      (make-element-line (* 0.7 diameter) thickness
                         (angle->unit-vector angle))
      (combine c (rotate c 90)
               (make-element-circle (/ diameter 2) thickness))))

Complete Radial Capacitors Script

The following is a complete example script I use to generate arbitrary footprints for radial capacitors, both polarized and unpolarized. First the main script itself:

  #! /usr/bin/guile \
--debug -e main -s !# ;;; ;;; radial-caps ;;; ;;; Copyright 2007 Dean Ferreyra, All rights reserved ;;; ;;; $Id: GEDAFootprintScriptLibrary.txt,v 1.11 2008/09/12 20:09:41 DeanFerreyra Exp $ ;;; Dean Ferreyra ;;; ;;; Radial capacitors ;;; (use-syntax (ice-9 syncase)) (use-modules (oop goops)) (use-modules (ice-9 getopt-long)) (use-modules (octw conditional) (octw anaphoric) (octw helper) (octw pads) (octw pads-scripting)) ;;; Load some default constants (load "defaults.scm") (define (usage) (format #t "usage: radial-caps.pads [options] <name> <description>~%") (format #t " <pin-pitch>~%") (format #t " <pin-diameter>~%") (format #t " <cap-diameter>~%") (format #t " -m, --mm distances in millimeters~%") (format #t " -i, --in distances in inches~%") (format #t " -c, --cmil distances in centimils~%") (format #t " -d, --drill=PERCENT drill hole growth as a percentage of~%") (format #t " pin diameter (defaults to ~A%)~%" (* 100 *drill-growth-percentage*)) (format #t " -a, --copper=PERCENT copper annulus as a percentage of~%") (format #t " drill hole diameter (defaults to ~A%)~%" (* 100 *copper-growth-percentage*)) (format #t " -p, --polar=NUMBER polarized capacitor with square pin for pin NUMBER ~%") (format #t " -h, --help this usage message~%") (exit 1)) (define option-spec `(,@(distance-units-option-spec) (drill (single-char #\d) (value #t)) (copper (single-char #\a) (value #t)) (polar (single-char #\p) (value #t)) (help (single-char #\h)))) (define (main args) (let* ((options (getopt-long (command-line) option-spec)) (parameters (option-ref options '() '()))) (when (option-ref options 'help #f) (usage)) (unless (= (length parameters) 5) (usage)) (defaults-set-evaled-options! options) (let-nth ((name (nth parameters)) (description (nth parameters)) (pin-pitch (evaled-string->cmil options (nth parameters))) (pin-diameter (evaled-string->cmil options (nth parameters))) (cap-diameter (evaled-string->cmil options (nth parameters)))) (unless (and (number? pin-pitch) (number? pin-diameter) (number? cap-diameter)) (usage)) (let* ((drill (* pin-diameter (+ 1 *drill-growth-percentage*))) (copper (copper-diameter drill))) (let ((polar-pin (aand (option-ref options 'polar #f) (string->number it)))) (let ((pins (compose-chain (p) (make <pin> #:thickness copper #:clearance-extent *clearance-extent* #:mask-extent *mask-extent* #:drill drill) (row p 2 pin-pitch 0) (enumerate* p 1) (or (and polar-pin (shape-square p (- polar-pin 1))) p))) (silk (combine (make-element-circle (/ cap-diameter 2) *silk-thickness*)))) (let ((elem (make <element> #:description description #:name name #:contents (combine pins silk)))) (output elem #t))))))))
and here is the defaults.scm file that provides some default values and specific helper functions that all my scripts load:
  ;;;
  ;;; defaults
  ;;;
  ;;; Copyright 2007 Dean Ferreyra, All rights reserved
  ;;;
  ;;; $Id: GEDAFootprintScriptLibrary.txt,v 1.11 2008/09/12 20:09:41 DeanFerreyra Exp $
  ;;; Dean Ferreyra
  
  ;;;
  ;;; Default values for common constants modifiable within other pads files.
  ;;;
  
  ;;; All distances in centimils
  
  (define *mask-extent*      1200)
  (define *clearance-extent* 1500)
  (define *silk-thickness*   1000)
  
  (define *drill-growth-percentage* (percent 15))
  (define *copper-growth-percentage* (percent 100))
  
  (define *copper-annulus-min* (mils->centimils 12))
  
  (define (defaults-set-evaled-options! options)
    (set-evaled-option! *drill-growth-percentage* options 'drill
                        percent)
    (set-evaled-option! *copper-growth-percentage* options 'copper
                        percent))
  
  (define (copper-diameter drill)
    (let ((copper (* drill (+ 1 *copper-growth-percentage*)))
          (min-copper (+ (* 2 *copper-annulus-min*) drill)))
      (max copper min-copper)))

Here is an example using the script from the bash command line, though typically the scripts are run from Make:

   $ ./radial-caps.pads --mm 'C?' --polar "CAPACITOR" 1 4.7 0.5 10 > CAP-10.0-4.7-P.fp
Here is the resulting footprint:
  Element["" "CAPACITOR" "C?" "" 0 0 0 0 0 100 ""] (
      Pin[-9252 0 4664 1500 7064 2264 "1" "1" "square"]
      Pin[9252 0 4664 1500 7064 2264 "2" "2" ""]
      ElementArc[0 0 19685 19685 0 360 1000]
  )
Topic attachments
  Attachment Size Date Comment
elsegz octw-guile-geda-modules-1.0.tar.gz 24.2 K 09 Sep 2008 - 22:01 gEDA Guile Library 1.0
r11 - 12 Sep 2008 - 20:09:41 - DeanFerreyraYou are here: Bourbon Street Software  >  GEDA > GEDAFootprintScriptLibrary
 
Home
NearlyFreeSpeech  This site is powered by the TWiki collaboration platform