english
version "1.0"
identify "xyz"
#: Copyright (c) 2000, 2003 by Wayne C. Gramlich.
#, All rights reserved.
#,
#, Permission to use, copy, modify, distribute, and sell this software
#, for any purpose is hereby granted without fee provided that the above
#, copyright notice and this permission are retained. The author makes
#, no representations about the suitability of this software for any purpose.
#, It is provided "as is" without express or implied warranty.
module mill
#: This module implements a Gerber photo plotter output generator.
define mill #: The plotter data
record
bar unsigned #: Magic constant
bottom mill_surface #: Bottom {mill_surface}
cell_size unsigned #: Steps per cell
cutter_depth unsigned #: Depth of trace cutter (in steps)
counter_sink_depth unsigned #: Depth of counter-sink
drill_depth unsigned #: Depth of drill plunge (in steps)
drills vector[vector[mill_node]] #: Sorted drills list
foo unsigned #: Magic constant
geometry geometry #: {geometry} object
schematic_capture logical #: {true} => schematic capture
shaved_size unsigned #: Size of a shaved via in steps
thick_diagonal unsigned #: Thick diagonal width in steps
thick_width unsigned #: Width of thick line in steps
thin_diagonal unsigned #: Thin diagonal width in steps
thin_width unsigned #: Width of thin line in steps
top mill_surface #: Top {mill_surface}
travel_height unsigned #: Height at which travel occurs
unshaved_size unsigned #: Size of an unshaved via in steps
x unsigned #: X coordinate
x_flipped logical #: {true}=>X coordinate flipped
y unsigned #: Y coordinate
zot unsigned #: Magic constant
generate allocate, erase, print
define mill_node #: One node of the mill
record
hole_size unsigned #: Size of hole (=0xffffffff for none)
segments vector[mill_segment] #: List of segments connected to node
shave_east logical #: Shave east side
shave_north logical #: Shave north side
shave_north_east logical #: Shave north east side
shave_north_west logical #: Shave nort west side
shave_south logical #: Shave south side
shave_south_east logical #: Shave south_east side
shave_south_west logical #: Shave south_west side
shave_west logical #: Shave west side
wire unsigned #: Wire number
x unsigned #: X coordinate
x_offset integer #: X offset
y unsigned #: Y coordinate
y_offset integer #: Y offset
generate address_get, allocate, erase, identical, print
define mill_point #: One end-point of a {mill_stroke}
record
strokes vector[mill_stroke] #: Strokes attached to {mill_point}
wire unsigned #: Wire associated with point
x unsigned #: X coordinate (in steps)
y unsigned #: Y coordinate (in steps)
generate address_get, allocate, erase, identical, print
define mill_segment
record
ccwx1 unsigned #: Counter clockwise x for {node1}
ccwx2 unsigned #: Counter clockwise x for {node2}
ccwy1 unsigned #: Counter clockwise y for {node1}
ccwy2 unsigned #: Counter clockwise y for {node2}
cwx1 unsigned #: Clockwise x for {node1}
cwx2 unsigned #: Clockwise x for {node2}
cwy1 unsigned #: Clockwise y for {node1}
cwy2 unsigned #: Clockwise y for {node2}
node1 mill_node #: One end-point
node2 mill_node #: Other end-point
thickness line_thickness #: Thickness of line
generate address_get, allocate, erase, identical, print
define mill_stroke #: One stroke of the mill
record
point1 mill_point #: First {mill_point}
point2 mill_point #: Second {mill_point}
wire unsigned #: Wire associated with stroke
generate address_get, allocate, erase, identical, print
define mill_surface #: One surface of milled PCB
record
mill mill #: Parent mill object
nodes vector[mill_node] #: List of {mill_node}'s
nodes_table set[mill_node] #: Table of {mill_node}'s
segments vector[mill_segment] #: List of {mill_segments}'s
strokes vector[mill_stroke] #: List of {mill_stroke}'s
points vector[mill_point] #: List of {mill_points}'s
points_table set[mill_point] #: Table of {mill_points}'s
temporary_node mill_node #: Temporary {mill_node}
temporary_point mill_point #: Temporary {mill_point}
generate address_get, allocate, erase, print
#: {mill} routines:
procedure characters_insert@mill
takes
mill mill
layer layer
x unsigned
y unsigned
characters_transpose logical
characters vector[unsigned]
returns logical
#: This procedure will insert {characters} into {mill} at ({x}, {y})
#, on {layer}. If {characters_transpose} is {true}, the characters
#, will be transposed. If any errors occur, {true} is returned
#, {false} otherwise.
procedure chunk_layer_insert@mill
takes
mill mill
layer layer
x unsigned
y unsigned
name string
returns logical
#: This procedure will insert a glyph into the output. Since
#, plotting does not support glyphs, this procedure is a no-op.
procedure create@mill
takes
geometry geometry
returns mill
#: This procedure will create and return a newly allocated {mill}
#, object containing {geometry}.
#, run between the pins of stand DIP package with pins on .1 inch
#, centers. The thick trace width is 50 mils (.050inch), This
#, means that there must be 25 mils of thick trace on each side
#, the component pins. This leaves 50 mils of space between the
#, edges of the thick traces. We need to run two isolation paths
#, and the signal trace in the remaining 50 mils. Thus,
#, 50 = 2 * isolation_width + 1 * thin_width.
#, out signal wire running between two pins travel in exactly the same
#, path when the pads are being cut out. If a pad is at grid location
#, (X,Y) and the signal is going through (X+1,Y), we want to be sure
#, that X*{cell_size}+{thick_width/2}+{isolation_width/2} =
#, (X+1)*{cell_size}-{thin_width/2}-{isolation_width/2}.
#, means that we want the cutter for two pads with no signal between the
#, pins to have the isolation cutter travel the same path. Thus, if
#, there are two pads at (X,Y) and (X+2,Y) we want the pad isolation
#, cut to be right between the two at (X+1,Y). This means that:
#, X*{cell_size} + {unshaved_width/2} + {isolation_width/2} =
#, (X+2)*{cell_size} - {unshaved_width/2} - {isolation_width/2} .
#, the X or Y axis; *not* the directly across the line:
#, {foo}, {bar}, and {zot}:
#, left/right of the a 45 degree line intersection the line edge meets on:
#, {isolation_width} variable.
#, of the trace line.
procedure connection_insert@mill
takes
mill mill
x unsigned
y unsigned
hole_number unsigned
returns logical
#: This procuedure will insert a via at ({x}, {y}) with a
#, hole number of {hole_number} in {mill}. {true} is returned
#, if there are any errors and {false} otherwise.
procedure control_generate@mill
takes
mill mill
control_stream out_stream
returns_nothing
#: This procedure will output the control commands for {mill} to
#, {control_stream}.
#, the origin on the flipped board. We assume that there are
#, only two registration holes. Assume that the origin is
#, near the "closest" registration hole. After flipping the
#, the board, the origin is next to the other hole.
procedure coordinate_helper@mill
takes
mill mill
number unsigned
out_stream out_stream
returns_nothing
#: This procedure will output {number} to {out_stream} using {mill}.
procedure coordinate_show@mill
takes
mill mill
label string
x unsigned
y unsigned
out_stream out_stream
returns_nothing
#: This procedure output ({x}, {y}) with {label} to {out_stream}.
procedure drill_or_counter_sink@mill
takes
mill mill
drill_start unsigned
drill_end unsigned
depth unsigned
message string
x_flipped logical
control_stream out_stream
returns_nothing
#: This procedure will output the commands to drill or counter_sink the
#, holes for the drills numbered from {drill_start} through {drill_end}
#, out to {control_stream}. The drill/counter-sink depth is set with
#, {depth}. A pause message is output containing {message}. {x_flipped}
#, is set to {true}@{logical} to make invert the x axis.
procedure generate@mill
takes
pcb_file_name string
mill_base_name string
outline logical
geometry geometry
pcb_timer timer
returns logical
#: This procedure will read in {pcb_file_name} and generate
#, a top and a bottom layer PCB mill file for {mill_base_name}.
procedure glyph_file_read@mill
takes
mill mill
characters_mirror logical
returns logical
#: This procedure is used to read the `glyph file'. Since we
#, don't support glyphs in milled output, this procedure is a no-op.
procedure line_draw@mill
takes
mill mill
layer layer
x1 unsigned
y1 unsigned
x2 unsigned
y2 unsigned
line_thickness line_thickness
returns logical
#: This procedure will draw a line of thickness {line_thickness}
#, from ({x1}, {y1}) to ({x2}, {y2}) on {layer} in {plot}.
#, If any error occurs, {true} is returned; otherwise {false}
#, is returned.
procedure move_to@mill
takes
mill mill
x unsigned
y unsigned
wire unsigned
control_stream out_stream
returns_nothing
#: This procedure will output a command to {control_stream}to move the
#, mill head of {mill} to ({x}, {y}).
procedure overcut_eliminate@mill
takes
mill mill
returns_nothing
#: This procedure will remove duplicate overcuts in {mill}.
procedure pause@mill
takes
mill mill
message string
control_stream out_stream
returns_nothing
#: This procedure will output a pause command to {control_stream}
#, using {message} as the message.
procedure strokes_generate@mill
takes
mill mill
returns_nothing
#: This procedure will generate a list of mill strokes for both
#, surfaces in {mill}.
procedure via_name_insert@mill
takes
mill mill
x unsigned
y unsigned
hole_number unsigned
name string
returns logical
#: This procuedure will insert a via at ({x}, {y}) with a hole
#, number of {hole_number} into {plot}. The via name in {name}
#, is ignored. {true} is returned if there are any errors and
#, {false} otherwise.
procedure vias_shave@mill
takes
mill mill
returns_nothing
#: This procedure will figure out which vias to shave on both
#, surfaces in {mill}.
procedure wires_assign@mill
takes
mill mill
returns_nothing
#: This procedure will assign wire nubmers the the various electricaly
#, connected {mill_node}'s in both surfaces of {mill}.
#: {mill_node} procedures:
procedure clockwise_locate@mill_node
takes
mill_node mill_node
direction direction
returns mill_segment
#: This procedure will search clockwise from {direction} in {mill_node}
#, to find the first {mill_segment} that intersects.
#, ??@{mill_segement} is returned if no segement can found.
procedure counter_clockwise_locate@mill_node
takes
mill_node mill_node
direction direction
returns mill_segment
#: This procedure will search counter clockwise from {direction} in
#, {mill_node} to find the first {mill_segment} that intersects.
#, ??@{mill_segement} is returned if no segement can found.
procedure create@mill_node
takes
x unsigned
y unsigned
returns mill_node
#: This procedure will create and return a new {mill_node} object
#, containing {x} and {y}.
procedure direction@mill_node
takes
node1 mill_node
node2 mill_node
returns direction
#: This procedure will return the {direction} from {node1} to {node2}.
procedure equal@mill_node
takes
mill_node1 mill_node
mill_node2 mill_node
returns logical
#: This procedure will return {true} if the coordinate of {mill_node1}
#, is equal to the coordinate of {mill_node2}.
procedure hash@mill_node
takes
mill_node mill_node
returns unsigned
#: This procedure will return a hash of {mill_node}.
procedure segment_append@mill_node
takes
mill_node mill_node
mill_segment mill_segment
returns_nothing
#: This procedure will append {mill_segment} to the segment list
#, in {mill_node}.
procedure stroke@mill_node
takes
mill_node mill_node
mill_surface mill_surface
mill mill
returns_nothing
#: This procedure will identify the end-points for each {mill_segment}
#, attached to {mill_node}. In addition, it will generate a list of
#, mill strokes for any via outlines needed for {mill_node} and append
#, them to the {mill_stroke} list in {mill_surface}.
#, acute (< 90 degrees) angles.
procedure wire_assign@mill_node
takes
mill_node mill_node
wire unsigned
indent unsigned
returns_nothing
#: This procedure will recursively assign {wire} to all of the
#, {mill_node}'s that are transitively connected to {mill_node}.
#: {mill_point} procedures:
procedure create@mill_point
takes
x unsigned
y unsigned
wire unsigned
returns mill_point
#: This procedure will create and return a {mill_point} containing
#, ({x}, {y}).
procedure compare@mill_point
takes
mill_point1 mill_point
mill_point2 mill_point
returns integer
#, {mill_point1} is less than, equal to, or greater than {mill_point2}.
procedure equal@mill_point
takes
mill_point1 mill_point
mill_point2 mill_point
returns logical
#: This procedure will return {true}@{logical} if {mill_point1} is
#, equal to {mill_point2} and {false} otherwise.
procedure hash@mill_point
takes
mill_point mill_point
returns unsigned
#: This procedure will return a hash of {mill_point}.
procedure stroke_append@mill_point
takes
mill_point mill_point
mill_stroke mill_stroke
returns_nothing
#: This procedure will append {mill_stroke} to the stroke list
#, in {mill_point}.
procedure stroke_remove@mill_point
takes
mill_point mill_point
mill_stroke mill_stroke
returns_nothing
#: This procedure will remove {mill_stroke} to the stroke list
#, in {mill_point}.
#: {mill_segment} procedures:
procedure ccw_select@mill_segment
takes
mill_segment mill_segment
mill_node mill_node
returns unsigned, unsigned
#: This procedure will return the counter clockwise coordinate of
#, {mill_segement} associated {mill_node}.
procedure ccw_set@mill_segment
takes
mill_segment mill_segment
mill_node mill_node
x unsigned
y unsigned
returns_nothing
#: This procedure will set the counter clockwise end point of
#, {mill_segment} associated with {mill_node} to ({x}, {y}).
procedure create@mill_segment
takes
mill_node1 mill_node
mill_node2 mill_node
line_thickness line_thickness
returns mill_segment
#: This procedure will create and return a {mill_segment} object
#, from {mill_node1} to {mill_node2} of thickness {line_thickness}.
procedure cw_select@mill_segment
takes
mill_segment mill_segment
mill_node mill_node
returns unsigned, unsigned
#: This procedure will return the clockwise coordinate of
#, {mill_segement} associated {mill_node}.
procedure cw_set@mill_segment
takes
mill_segment mill_segment
mill_node mill_node
x unsigned
y unsigned
returns_nothing
#: This procedure will set the clockwise end point of
#, {mill_segment} associated with {mill_node} to ({x}, {y}).
procedure compare@mill_segment
takes
mill_segment1 mill_segment
mill_segment2 mill_segment
returns integer
#: This procedure will return -1, 0, or 1 depending upon whether
#, {mill_segment1} is counter clockwise, equal to, or counter clockwise
#, {mill_segment2}. Both {mill_segment1} and {mill_segment2} must
#, have a common {mill_node}.
procedure direction@mill_segment
takes
mill_segment mill_segment
mill_node mill_node
returns direction
#: This procedure will return the direction of {mill_segment}
#, in relation to {mill_node}.
procedure is_thick@mill_segment
takes
mill_segment mill_segment
returns logical
#: This procedure will return {true}@{logical} if {mill_segment}
#, is thick and {false} otherwise.
procedure is_thin@mill_segment
takes
mill_segment mill_segment
returns logical
#: This procedure will return {true}@{logical} if {mill_segment}
#, is thin and {false} otherwise.
procedure segment_select@mill_segment
takes
segment1 mill_segment
segment2 mill_segment
returns mill_segment
#: This procedure will return the thicker of {segment1} and {segment2}
#, where a segment of ??@{mill_segment} is considered to have zero
#, thickness. Warning messages are generated when a thick line
#, is supressing a thin line.
#, This is probably a mistake.
procedure show@mill_segment
takes
mill_segment mill_segment
label string
out_stream out_stream
returns_nothing
procedure stroke@mill_segment
takes
mill_segment mill_segment
mill_surface mill_surface
returns_nothing
#: This proceudure will add the strokes for {mill_segment} to the
#, {mill_stroke} list in {mill_surface}.
procedure wire_assign@mill_segment
takes
mill_segment mill_segment
wire unsigned
indent unsigned
returns_nothing
#: This procedure will recursively assign {wire} to all {mill_node}'s
#, that are electrically connected to {mill_segment}.
#: {mill_stroke} procedures:
procedure compare@mill_stroke
takes
stroke1 mill_stroke
stroke2 mill_stroke
returns integer
#: This procedure will return -1, 0, or 1 depending upon whether {stroke1}
#, is "less than", "equal to" or "greater than" {stroke2}. {stroke1} and
#, {stroke2} must be on the same horizontal, vertical, or diagonal line.
procedure create@mill_stroke
takes
point1 mill_point
point2 mill_point
wire unsigned
returns mill_stroke
#: This procedure will create and return a new {mill_stroke} object
#, from {point1} to {point2}.
#: {mill_surface} procedures:
procedure adjoin@mill_surface
takes
mill_surface mill_surface
mill_node mill_node
direction direction
returns logical
#: This procedure will return {true}@{logical} if there is a pad in
#, {direction} from {mill_node} that is electrically connected to
#, it (and there is no intervening signal wire.
procedure control_generate@mill_surface
takes
mill_surface mill_surface
mill mill
x_flipped logical
control_stream out_stream
returns_nothing
#: This procedure will output the control commands for {mill_surface} to
#, {control_stream}. {x_flipped} is set to true to invert the
#, x direction.
procedure create@mill_surface
takes
mill mill
returns mill_surface
#: This procedure will create and return a new {surface} object.
procedure fetch2@mill_surface
takes
mill_surface mill_surface
x unsigned
y unsigned
returns mill_node
#: This procedure will fetch the {mill_node} from {mill_surface} at
#, ({x}:{y}). If there is no such {mill_node} at ({x}:{y}),
#, ??@{mill_node} is returned.
procedure node_insert@mill_surface
takes
mill_surface mill_surface
x unsigned
y unsigned
returns mill_node
#: This procedure return the node at ({x}, {y}) in {mill_surface}.
#, If such a node does not already exist, it will be created.
procedure notch@mill_surface
takes
mill_surface mill_surface
mill_node mill_node
direction direction
returns logical
#: This procedure will return {true}@{logical} if the {direction} corner
#, of {mill_node} should be notched. This only occurs when an signal
#, wire makes a right angle bend at the {direction} corner of {mill_node}.
procedure overcut_eliminate@mill_surface
takes
mill_surface mill_surface
returns_nothing
#: This procedure will go through all of the strokes in {mill_surface},
#, detect overcuts, and eliminate them.
procedure overcut_eliminate_scan@mill_surface
takes
mill_surface mill_surface
table table[integer, vector[mill_stroke]]
keys vector[integer]
returns_nothing
#: This procedure scan through each key in {keys} and cull out any
#, duplicate over cuts. The remaining strokes are appended to
#, {mill_surface}.{strokes}.
procedure overcut_eliminate_group@mill_surface
takes
mill_surface mill_surface
strokes vector[mill_stroke]
set set[mill_point]
key integer
returns_nothing
#: ...
procedure overcut_eliminate_join@mill_surface
takes
mill_surface mill_surface
points vector[mill_point]
set set[mill_point]
returns_nothing
#: ....
#put@("\n\", debug_stream)
procedure overcut_eliminate_insert@mill_surface
takes
table table[integer, vector[mill_stroke]]
keys vector[integer]
key integer
stroke mill_stroke
returns_nothing
#: This procedure will insert {stroke} in {table} and {keys} as necessary.
procedure point_create@mill_surface
takes
mill_surface mill_surface
x unsigned
y unsigned
wire unsigned
returns mill_point
#: This procedure will return the {mill_point} assoicated with
#, ({x}, {y}) in {mill_surface}.
procedure segment_insert@mill_surface
takes
mill_surface mill_surface
x1 unsigned
y1 unsigned
x2 unsigned
y2 unsigned
line_thickness line_thickness
returns_nothing
#: This procedure will insert a segment from ({x1}, {y1}) to ({x2}, {y2})
#, of thickness {line_thickness} into {mill_surface}.
procedure stroke_append@mill_surface
takes
mill_surface mill_surface
x1 unsigned
y1 unsigned
x2 unsigned
y2 unsigned
wire unsigned
flags unsigned
returns_nothing
#: This procedure will create a {mill_stroke} object containing
#, {x1}, {y1}, {x2}, and {y2} and append it to the strokes list
#, in {mill_surface}.
procedure strokes_generate@mill_surface
takes
mill_surface mill_surface
mill mill
returns_nothing
#: This procedure will generate the {mill_stroke}'s list for {mill_surface}.
procedure via_shave@mill_surface
routine_types
procedure shave_set
takes mill_node, logical
returns_nothing
takes
mill_surface mill_surface
x unsigned
y unsigned
direction direction
shave_set shave_set
returns_nothing
#: This procedure will cause any via at ({x}, {y}) in {mill_surface}
#, to be shaved using the {shave_set} if there is no segment in
#, {direction}.
procedure wires_assign@mill_surface
takes
mill_surface mill_surface
returns_nothing
#: This procedure will figure out which nodes are electrically
#, connected to one another. This is used for isolation path
#, selection. We try to keep the cutter on one trace at a time.
procedure vias_shave@mill_surface
takes
mill_surface mill_surface
returns_nothing
#: This procedure will figure out which vias to shave on the nodes
#, for {mill_surface}.