freerouting/src/main/java/eu/mihosoft/freerouting/designformats/specctra/Package.java

505 lines
19 KiB
Java

/*
* Copyright (C) 2014 Alfons Wirtz
* website www.freerouting.net
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License at <http://www.gnu.org/licenses/>
* for more details.
*
* Package.java
*
* Created on 21. Mai 2004, 09:31
*/
package designformats.specctra;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import board.Item;
/**
* Class for reading and writing package scopes from dsn-files.
*
* @author alfons
*/
public class Package
{
/** Creates a new instance of Package */
public Package(String p_name, PinInfo[] p_pin_info_arr, Collection<Shape> p_outline, Collection<Shape.ReadAreaScopeResult> p_keepouts,
Collection<Shape.ReadAreaScopeResult> p_via_keepouts, Collection<Shape.ReadAreaScopeResult> p_place_keepouts, boolean p_is_front)
{
name = p_name;
pin_info_arr = p_pin_info_arr;
outline = p_outline;
keepouts = p_keepouts;
via_keepouts = p_via_keepouts;
place_keepouts = p_place_keepouts;
is_front = p_is_front;
}
public static Package read_scope(Scanner p_scanner, LayerStructure p_layer_structure)
{
try
{
boolean is_front = true;
Collection <Shape> outline = new LinkedList<Shape>();
Collection<Shape.ReadAreaScopeResult> keepouts = new LinkedList<Shape.ReadAreaScopeResult>();
Collection<Shape.ReadAreaScopeResult> via_keepouts = new LinkedList<Shape.ReadAreaScopeResult>();
Collection<Shape.ReadAreaScopeResult> place_keepouts = new LinkedList<Shape.ReadAreaScopeResult>();
Object next_token = p_scanner.next_token();
if ( !(next_token instanceof String))
{
System.out.println("Package.read_scope: String expected");
return null;
}
String package_name = (String) next_token;
Collection<PinInfo> pin_info_list = new LinkedList<PinInfo>();
for (;;)
{
Object prev_token = next_token;
next_token = p_scanner.next_token();
if (next_token == null)
{
System.out.println("Package.read_scope: unexpected end of file");
return null;
}
if (next_token == Keyword.CLOSED_BRACKET)
{
// end of scope
break;
}
if (prev_token == Keyword.OPEN_BRACKET)
{
if (next_token == Keyword.PIN)
{
PinInfo next_pin = read_pin_info(p_scanner);
if (next_pin == null)
{
return null;
}
pin_info_list.add(next_pin);
}
else if (next_token == Keyword.SIDE)
{
is_front = read_placement_side(p_scanner);
}
else if (next_token == Keyword.OUTLINE)
{
Shape curr_shape = Shape.read_scope(p_scanner, p_layer_structure);
if (curr_shape != null)
{
outline.add(curr_shape);
}
// overread closing bracket
next_token = p_scanner.next_token();
if (next_token != Keyword.CLOSED_BRACKET)
{
System.out.println("Package.read_scope: closed bracket expected");
return null;
}
}
else if (next_token == Keyword.KEEPOUT)
{
Shape.ReadAreaScopeResult keepout_area = Shape.read_area_scope(p_scanner, p_layer_structure, false);
if (keepout_area != null)
{
keepouts.add(keepout_area);
}
}
else if (next_token == Keyword.VIA_KEEPOUT)
{
Shape.ReadAreaScopeResult keepout_area = Shape.read_area_scope(p_scanner, p_layer_structure, false);
if (keepout_area != null)
{
via_keepouts.add(keepout_area);
}
}
else if (next_token == Keyword.PLACE_KEEPOUT)
{
Shape.ReadAreaScopeResult keepout_area = Shape.read_area_scope(p_scanner, p_layer_structure, false);
if (keepout_area != null)
{
place_keepouts.add(keepout_area);
}
}
else
{
ScopeKeyword.skip_scope(p_scanner);
}
}
}
PinInfo [] pin_info_arr = new PinInfo[pin_info_list.size()];
Iterator<PinInfo> it = pin_info_list.iterator();
for (int i = 0; i < pin_info_arr.length; ++i)
{
pin_info_arr[i] = it.next();
}
return new Package(package_name, pin_info_arr, outline, keepouts, via_keepouts, place_keepouts, is_front);
}
catch (java.io.IOException e)
{
System.out.println("Package.read_scope: IO error scanning file");
System.out.println(e);
return null;
}
}
public static void write_scope(WriteScopeParameter p_par, library.Package p_package) throws java.io.IOException
{
p_par.file.start_scope();
p_par.file.write("image ");
p_par.identifier_type.write(p_package.name, p_par.file);
// write the placement side of the package
p_par.file.new_line();
p_par.file.write("(side ");
if (p_package.is_front)
{
p_par.file.write("front)");
}
else
{
p_par.file.write("back)");
}
// write the pins of the package
for (int i = 0; i < p_package.pin_count(); ++i)
{
library.Package.Pin curr_pin = p_package.get_pin(i);
p_par.file.new_line();
p_par.file.write("(pin ");
library.Padstack curr_padstack = p_par.board.library.padstacks.get(curr_pin.padstack_no);
p_par.identifier_type.write(curr_padstack.name, p_par.file);
p_par.file.write(" ");
p_par.identifier_type.write(curr_pin.name, p_par.file);
double [] rel_coor = p_par.coordinate_transform.board_to_dsn(curr_pin.relative_location);
for(int j = 0; j < rel_coor.length; ++j)
{
p_par.file.write(" ");
p_par.file.write((new Double(rel_coor[j])).toString());
}
int rotation = (int) Math.round(curr_pin.rotation_in_degree);
if (rotation != 0)
{
p_par.file.write("(rotate ");
p_par.file.write((new Integer(rotation)).toString());
p_par.file.write(")");
}
p_par.file.write(")");
}
// write the keepouts belonging to the package.
for (int i = 0; i < p_package.keepout_arr.length; ++i)
{
write_package_keepout(p_package.keepout_arr[i], p_par, false);
}
for (int i = 0; i < p_package.via_keepout_arr.length; ++i)
{
write_package_keepout(p_package.via_keepout_arr[i], p_par, true);
}
// write the package outline.
for (int i = 0; i < p_package.outline.length; ++i)
{
p_par.file.start_scope();
p_par.file.write("outline");
Shape curr_outline = p_par.coordinate_transform.board_to_dsn_rel(p_package.outline[i], Layer.SIGNAL);
curr_outline.write_scope(p_par.file, p_par.identifier_type);
p_par.file.end_scope();
}
p_par.file.end_scope();
}
private static void write_package_keepout(library.Package.Keepout p_keepout, WriteScopeParameter p_par,
boolean p_is_via_keepout) throws java.io.IOException
{
Layer keepout_layer;
if (p_keepout.layer >= 0)
{
board.Layer board_layer = p_par.board.layer_structure.arr[p_keepout.layer];
keepout_layer = new Layer(board_layer.name, p_keepout.layer, board_layer.is_signal);
}
else
{
keepout_layer = Layer.SIGNAL;
}
geometry.planar.Shape boundary_shape;
geometry.planar.Shape [] holes;
if (p_keepout.area instanceof geometry.planar.Shape)
{
boundary_shape = (geometry.planar.Shape) p_keepout.area ;
holes = new geometry.planar.Shape [0];
}
else
{
boundary_shape = p_keepout.area .get_border();
holes = p_keepout.area .get_holes();
}
p_par.file.start_scope();
if (p_is_via_keepout)
{
p_par.file.write("via_keepout");
}
else
{
p_par.file.write("keepout");
}
Shape dsn_shape = p_par.coordinate_transform.board_to_dsn(boundary_shape, keepout_layer);
if (dsn_shape != null)
{
dsn_shape.write_scope(p_par.file, p_par.identifier_type);
}
for (int j = 0; j < holes.length; ++j)
{
Shape dsn_hole = p_par.coordinate_transform.board_to_dsn(holes[j], keepout_layer);
dsn_hole.write_hole_scope(p_par.file, p_par.identifier_type);
}
p_par.file.end_scope();
}
/** Reads the information of a single pin in a package. */
private static PinInfo read_pin_info(Scanner p_scanner)
{
try
{
// Read the padstack name.
p_scanner.yybegin(SpecctraFileScanner.NAME);
String padstack_name = null;
Object next_token = p_scanner.next_token();
if ( next_token instanceof String)
{
padstack_name = (String) next_token;
}
else if ( next_token instanceof Integer)
{
padstack_name = ((Integer) next_token).toString();
}
else
{
System.out.println("Package.read_pin_info: String or Integer expected");
return null;
}
double rotation = 0;
p_scanner.yybegin(SpecctraFileScanner.NAME); // to be able to handle pin names starting with a digit.
next_token = p_scanner.next_token();
if (next_token == Keyword.OPEN_BRACKET)
{
// read the padstack rotation
next_token = p_scanner.next_token();
if (next_token == Keyword.ROTATE)
{
rotation = read_rotation(p_scanner);
}
else
{
ScopeKeyword.skip_scope(p_scanner);
}
p_scanner.yybegin(SpecctraFileScanner.NAME);
next_token = p_scanner.next_token();
}
// Read the pin name.
String pin_name = null;
if ( next_token instanceof String)
{
pin_name = (String) next_token;
}
else if ( next_token instanceof Integer)
{
pin_name = ((Integer) next_token).toString();
}
else
{
System.out.println("Package.read_pin_info: String or Integer expected");
return null;
}
double [] pin_coor = new double [2];
for (int i = 0; i < 2; ++i)
{
next_token = p_scanner.next_token();
if (next_token instanceof Double)
{
pin_coor[i] = ((Double) next_token).doubleValue();
}
else if (next_token instanceof Integer)
{
pin_coor[i] = ((Integer) next_token).intValue();
}
else
{
System.out.println("Package.read_pin_info: number expected");
return null;
}
}
// Handle scopes at the end of the pin scope.
for (;;)
{
Object prev_token = next_token;
next_token = p_scanner.next_token();
if (next_token == null)
{
System.out.println("Package.read_pin_info: unexpected end of file");
return null;
}
if (next_token == Keyword.CLOSED_BRACKET)
{
// end of scope
break;
}
if (prev_token == Keyword.OPEN_BRACKET)
{
if (next_token == Keyword.ROTATE)
{
rotation = read_rotation(p_scanner);
}
else
{
ScopeKeyword.skip_scope(p_scanner);
}
}
}
return new PinInfo(padstack_name, pin_name, pin_coor, rotation);
}
catch (java.io.IOException e)
{
System.out.println("Package.read_pin_info: IO error while scanning file");
return null;
}
}
private static double read_rotation(Scanner p_scanner)
{
double result = 0;
try
{
Object next_token = p_scanner.next_token();
if (next_token instanceof Integer)
{
result = ((Integer)next_token).intValue();
}
else if (next_token instanceof Double)
{
result = ((Double)next_token).doubleValue();
}
else
{
System.out.println("Package.read_rotation: number expected");
}
// Overread The closing bracket.
next_token = p_scanner.next_token();
if (next_token != Keyword.CLOSED_BRACKET)
{
System.out.println("Package.read_rotation: closing bracket expected");
}
}
catch (java.io.IOException e)
{
System.out.println("Package.read_rotation: IO error while scanning file");
}
return result;
}
/**
* Writes the placements of p_package to a Specctra dsn-file.
*/
public static void write_placement_scope(WriteScopeParameter p_par, library.Package p_package)
throws java.io.IOException
{
Collection<Item> board_items = p_par.board.get_items();
boolean component_found = false;
for (int i = 1; i <= p_par.board.components.count(); ++i)
{
board.Component curr_component = p_par.board.components.get(i);
if (curr_component.get_package() == p_package)
{
// check, if not all items of the component are deleted
boolean undeleted_item_found = false;
Iterator<Item> it = board_items.iterator();
while (it.hasNext())
{
Item curr_item = it.next();
if (curr_item.get_component_no() == curr_component.no)
{
undeleted_item_found = true;
break;
}
}
if (undeleted_item_found || !curr_component.is_placed())
{
if (!component_found)
{
// write the scope header
p_par.file.start_scope();
p_par.file.write("component ");
p_par.identifier_type.write(p_package.name, p_par.file);
component_found = true;
}
Component.write_scope(p_par, curr_component);
}
}
}
if (component_found)
{
p_par.file.end_scope();
}
}
private static boolean read_placement_side(Scanner p_scanner) throws java.io.IOException
{
Object next_token = p_scanner.next_token();
boolean result = (next_token != Keyword.BACK);
next_token = p_scanner.next_token();
if (next_token != Keyword.CLOSED_BRACKET)
{
System.out.println("Package.read_placement_side: closing bracket expected");
}
return result;
}
public final String name;
/** List of objects of type PinInfo. */
public final PinInfo[] pin_info_arr;
/** The outline of the package. */
public final Collection<Shape> outline;
/** Collection of keepoouts belonging to this package */
public final Collection<Shape.ReadAreaScopeResult> keepouts;
/** Collection of via keepoouts belonging to this package */
public final Collection<Shape.ReadAreaScopeResult> via_keepouts;
/** Collection of place keepoouts belonging to this package */
public final Collection<Shape.ReadAreaScopeResult> place_keepouts;
/** If false, the package is placed on the back side of the board */
public final boolean is_front;
/** Describes the Iinformation of a pin in a package. */
static public class PinInfo
{
PinInfo(String p_padstack_name, String p_pin_name, double [] p_rel_coor, double p_rotation)
{
padstack_name = p_padstack_name;
pin_name = p_pin_name;
rel_coor = p_rel_coor;
rotation = p_rotation;
}
/** Phe name of the pastack of this pin. */
public final String padstack_name;
/** Phe name of this pin. */
public final String pin_name;
/** The x- and y-coordinates relative to the package location. */
public final double [] rel_coor;
/** The rotation of the pin relative to the package. */
public final double rotation;
}
}