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
}.