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

522 lines
20 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.
*
* SessionFile.java
*
* Created on 29. Oktober 2004, 08:01
*/
package designformats.specctra;
import java.util.Collection;
import java.util.Iterator;
import geometry.planar.FloatPoint;
import geometry.planar.Point;
import board.BasicBoard;
import board.PolylineTrace;
import board.Via;
import board.ConductionArea;
import datastructures.IndentFileWriter;
import datastructures.IdentifierType;
/**
* Methods to handle a Specctra session file.
*
* @author alfons
*/
public class SessionFile
{
/**
* Creates a Specctra session file to update the host system from the RoutingBooard
*/
public static boolean write( BasicBoard p_board, java.io.OutputStream p_output_stream, String p_design_name)
{
if (p_output_stream == null)
{
return false;
}
IndentFileWriter output_file = null;
try
{
output_file = new IndentFileWriter(p_output_stream);
}
catch (Exception e)
{
System.out.println("unable to create session file");
return false;
}
String session_name = p_design_name.replace(".dsn", ".ses");
try
{
String [] reserved_chars = {"(", ")", " ", "-"};
IdentifierType identifier_type = new IdentifierType(reserved_chars, p_board.communication.specctra_parser_info.string_quote);
write_session_scope(p_board, identifier_type, output_file, session_name, p_design_name);
}
catch (java.io.IOException e)
{
System.out.println("unable to write session file");
return false;
}
try
{
output_file.close();
}
catch (java.io.IOException e)
{
System.out.println("unable to close session file");
return false;
}
return true;
}
private static void write_session_scope(BasicBoard p_board, IdentifierType p_identifier_type,
IndentFileWriter p_file, String p_session_name, String p_design_name) throws java.io.IOException
{
double scale_factor = p_board.communication.coordinate_transform.dsn_to_board(1)/p_board.communication.resolution;
CoordinateTransform coordinate_transform = new CoordinateTransform(scale_factor, 0, 0);
p_file.start_scope();
p_file.write("session ");
p_identifier_type.write(p_session_name, p_file);
p_file.new_line();
p_file.write("(base_design ");
p_identifier_type.write(p_design_name, p_file);
p_file.write(")");
write_placement(p_board, p_identifier_type, coordinate_transform, p_file);
write_was_is(p_board, p_identifier_type, p_file);
write_routes(p_board, p_identifier_type, coordinate_transform, p_file);
p_file.end_scope();
}
public static void write_placement(BasicBoard p_board, IdentifierType p_identifier_type,
CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException
{
p_file.start_scope();
p_file.write("placement");
Resolution.write_scope(p_file, p_board.communication);
for (int i = 1; i <= p_board.library.packages.count(); ++i)
{
write_components(p_board, p_identifier_type, p_coordinate_transform, p_file, p_board.library.packages.get(i));
}
p_file.end_scope();
}
/**
* Writes all components with the package p_package to the session file.
*/
public static void write_components(BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform,
IndentFileWriter p_file, library.Package p_package) throws java.io.IOException
{
Collection<board.Item> board_items = p_board.get_items();
boolean component_found = false;
for (int i = 1; i <= p_board.components.count(); ++i)
{
board.Component curr_component = p_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<board.Item> it = board_items.iterator();
while (it.hasNext())
{
board.Item curr_item = it.next();
if (curr_item.get_component_no() == curr_component.no)
{
undeleted_item_found = true;
break;
}
}
if (undeleted_item_found)
{
if (!component_found)
{
// write the scope header
p_file.start_scope();
p_file.write("component ");
p_identifier_type.write(p_package.name, p_file);
component_found = true;
}
write_component(p_board, p_identifier_type, p_coordinate_transform, p_file, curr_component);
}
}
}
if (component_found)
{
p_file.end_scope();
}
}
public static void write_component(BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform,
IndentFileWriter p_file, board.Component p_component) throws java.io.IOException
{
p_file.new_line();
p_file.write("(place ");
p_identifier_type.write(p_component.name, p_file);
double[] location = p_coordinate_transform.board_to_dsn(p_component.get_location().to_float());
Integer x_coor = (int) Math.round(location[0]);
Integer y_coor = (int) Math.round(location[1]);
p_file.write(" ");
p_file.write(x_coor.toString());
p_file.write(" ");
p_file.write(y_coor.toString());
if (p_component.placed_on_front())
{
p_file.write(" front ");
}
else
{
p_file.write(" back ");
}
int rotation = (int) Math.round(p_component.get_rotation_in_degree());
p_file.write((new Integer(rotation).toString()));
if (p_component.position_fixed)
{
p_file.new_line();
p_file.write(" (lock_type position)");
}
p_file.write(")");
}
public static void write_was_is(BasicBoard p_board, IdentifierType p_identifier_type,
IndentFileWriter p_file) throws java.io.IOException
{
p_file.start_scope();
p_file.write("was_is");
Collection<board.Pin> board_pins = p_board.get_pins();
for (board.Pin curr_pin : board_pins)
{
board.Pin swapped_with = curr_pin.get_changed_to();
if (curr_pin.get_changed_to() != curr_pin)
{
p_file.new_line();
p_file.write("(pins ");
board.Component curr_cmp = p_board.components.get(curr_pin.get_component_no());
if (curr_cmp != null)
{
p_identifier_type.write(curr_cmp.name, p_file);
p_file.write("-");
library.Package.Pin package_pin = curr_cmp.get_package().get_pin(curr_pin.get_index_in_package());
p_identifier_type.write(package_pin.name, p_file);
}
else
{
System.out.println("SessionFile.write_was_is: component not found");
}
p_file.write(" ");
board.Component swap_cmp = p_board.components.get(swapped_with.get_component_no());
if (swap_cmp != null)
{
p_identifier_type.write(swap_cmp.name, p_file);
p_file.write("-");
library.Package.Pin package_pin = swap_cmp.get_package().get_pin(swapped_with.get_index_in_package());
p_identifier_type.write(package_pin.name, p_file);
}
else
{
System.out.println("SessionFile.write_was_is: component not found");
}
p_file.write(")");
}
}
p_file.end_scope();
}
private static void write_routes(BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform,
IndentFileWriter p_file) throws java.io.IOException
{
p_file.start_scope();
p_file.write("routes ");
Resolution.write_scope(p_file, p_board.communication);
Parser.write_scope(p_file,p_board.communication.specctra_parser_info, p_identifier_type, true);
write_library(p_board, p_identifier_type, p_coordinate_transform, p_file);
write_network(p_board, p_identifier_type, p_coordinate_transform, p_file);
p_file.end_scope();
}
private static void write_library(BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform,
IndentFileWriter p_file) throws java.io.IOException
{
p_file.start_scope();
p_file.write("library_out ");
for (int i = 0; i < p_board.library.via_padstack_count(); ++i)
{
write_padstack(p_board.library.get_via_padstack(i), p_board, p_identifier_type, p_coordinate_transform, p_file);
}
p_file.end_scope();
}
private static void write_padstack(library.Padstack p_padstack, BasicBoard p_board, IdentifierType p_identifier_type,
CoordinateTransform p_coordinate_transform, IndentFileWriter p_file)
throws java.io.IOException
{
// search the layer range of the padstack
int first_layer_no = 0;
while (first_layer_no < p_board.get_layer_count())
{
if (p_padstack.get_shape(first_layer_no) != null)
{
break;
}
++first_layer_no;
}
int last_layer_no = p_board.get_layer_count() - 1;
while (last_layer_no >= 0 )
{
if (p_padstack.get_shape(last_layer_no) != null)
{
break;
}
--last_layer_no;
}
if (first_layer_no >= p_board.get_layer_count() || last_layer_no < 0)
{
System.out.println("SessionFile.write_padstack: padstack shape not found");
return;
}
p_file.start_scope();
p_file.write("padstack ");
p_identifier_type.write(p_padstack.name, p_file);
for (int i = first_layer_no; i <= last_layer_no; ++i)
{
geometry.planar.Shape curr_board_shape = p_padstack.get_shape(i);
if (curr_board_shape == null)
{
continue;
}
board.Layer board_layer = p_board.layer_structure.arr[i];
Layer curr_layer = new Layer(board_layer.name, i, board_layer.is_signal);
Shape curr_shape = p_coordinate_transform.board_to_dsn_rel(curr_board_shape, curr_layer);
p_file.start_scope();
p_file.write("shape");
curr_shape.write_scope_int(p_file, p_identifier_type);
p_file.end_scope();
}
if (!p_padstack.attach_allowed)
{
p_file.new_line();
p_file.write("(attach off)");
}
p_file.end_scope();
}
private static void write_network(BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform,
IndentFileWriter p_file) throws java.io.IOException
{
p_file.start_scope();
p_file.write("network_out ");
for (int i = 1; i <= p_board.rules.nets.max_net_no(); ++i)
{
write_net(i, p_board, p_identifier_type, p_coordinate_transform, p_file);
}
p_file.end_scope();
}
private static void write_net(int p_net_no, BasicBoard p_board, IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform,
IndentFileWriter p_file) throws java.io.IOException
{
Collection<board.Item> net_items = p_board.get_connectable_items(p_net_no);
boolean header_written = false;
Iterator<board.Item> it = net_items.iterator();
while (it.hasNext())
{
board.Item curr_item = it.next();
if (curr_item.get_fixed_state() == board.FixedState.SYSTEM_FIXED)
{
continue;
}
boolean is_wire = curr_item instanceof PolylineTrace;
boolean is_via = curr_item instanceof Via;
boolean is_conduction_area = curr_item instanceof ConductionArea
&& p_board.layer_structure.arr [curr_item.first_layer()].is_signal;
if (!header_written && (is_wire || is_via || is_conduction_area))
{
p_file.start_scope();
p_file.write("net ");
rules.Net curr_net = p_board.rules.nets.get(p_net_no);
if (curr_net == null)
{
System.out.println("SessionFile.write_net: net not found");
}
else
{
p_identifier_type.write(curr_net.name, p_file);
}
header_written = true;
}
if (is_wire)
{
write_wire((PolylineTrace)curr_item, p_board, p_identifier_type, p_coordinate_transform, p_file);
}
else if (is_via)
{
write_via((Via) curr_item, p_board, p_identifier_type, p_coordinate_transform, p_file);
}
else if (is_conduction_area)
{
write_conduction_area( (ConductionArea) curr_item, p_board, p_identifier_type,
p_coordinate_transform, p_file);
}
}
if (header_written)
{
p_file.end_scope();
}
}
private static void write_wire(PolylineTrace p_wire, BasicBoard p_board, IdentifierType p_identifier_type,
CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException
{
int layer_no = p_wire.get_layer();
board.Layer board_layer = p_board.layer_structure.arr[layer_no];
int wire_width = (int) Math.round(p_coordinate_transform.board_to_dsn(2 * p_wire.get_half_width()));
p_file.start_scope();
p_file.write("wire");
Point[] corner_arr = p_wire.polyline().corner_arr();
int [] coors = new int [2 * corner_arr.length];
int corner_index = 0;
int [] prev_coors = null;
for (int i = 0; i < corner_arr.length; ++i)
{
double[] curr_float_coors = p_coordinate_transform.board_to_dsn(corner_arr[i].to_float());
int [] curr_coors = new int[2];
curr_coors[0] = (int) Math.round(curr_float_coors[0]);
curr_coors[1] = (int) Math.round(curr_float_coors[1]);
if (i == 0 || ( curr_coors[0] != prev_coors[0] || curr_coors[1] != prev_coors[1]))
{
coors[corner_index] = curr_coors[0];
++corner_index;
coors[corner_index] = curr_coors[1];
++corner_index;
prev_coors = curr_coors;
}
}
if (corner_index < coors.length)
{
int [] adjusted_coors = new int[corner_index];
for (int i = 0; i < adjusted_coors.length; ++i)
{
adjusted_coors[i] = coors[i];
}
coors = adjusted_coors;
}
write_path(board_layer.name, wire_width, coors, p_identifier_type, p_file);
write_fixed_state(p_file, p_wire.get_fixed_state());
p_file.end_scope();
}
private static void write_via(Via p_via, BasicBoard p_board, IdentifierType p_identifier_type,
CoordinateTransform p_coordinate_transform, IndentFileWriter p_file) throws java.io.IOException
{
library.Padstack via_padstack = p_via.get_padstack();
FloatPoint via_location = p_via.get_center().to_float();
p_file.start_scope();
p_file.write("via ");
p_identifier_type.write(via_padstack.name, p_file);
p_file.write(" ");
double[] location = p_coordinate_transform.board_to_dsn(via_location);
Integer x_coor = (int) Math.round(location[0]);
p_file.write(x_coor.toString());
p_file.write(" ");
Integer y_coor = (int) Math.round(location[1]);
p_file.write(y_coor.toString());
write_fixed_state(p_file, p_via.get_fixed_state());
p_file.end_scope();
}
static private void write_fixed_state(IndentFileWriter p_file, board.FixedState p_fixed_state) throws java.io.IOException
{
if (p_fixed_state.ordinal() <= board.FixedState.SHOVE_FIXED.ordinal())
{
return;
}
p_file.new_line();
p_file.write("(type ");
if (p_fixed_state == board.FixedState.SYSTEM_FIXED)
{
p_file.write("fix)");
}
else
{
p_file.write("protect)");
}
}
private static void write_path(String p_layer_name, int p_width, int[] p_coors, IdentifierType p_identifier_type,
IndentFileWriter p_file)
throws java.io.IOException
{
p_file.start_scope();
p_file.write("path ");
p_identifier_type.write(p_layer_name, p_file);
p_file.write(" ");
p_file.write((new Integer(p_width)).toString());
int corner_count = p_coors.length/ 2;
for (int i = 0; i < corner_count; ++i)
{
p_file.new_line();
p_file.write(new Integer(p_coors[2 * i]).toString());
p_file.write(" ");
p_file.write(new Integer(p_coors[2 * i + 1]).toString());
}
p_file.end_scope();
}
private static void write_conduction_area( ConductionArea p_conduction_area, BasicBoard p_board,
IdentifierType p_identifier_type, CoordinateTransform p_coordinate_transform,
IndentFileWriter p_file) throws java.io.IOException
{
int net_count = p_conduction_area.net_count();
if (net_count <= 0 || net_count > 1)
{
System.out.println("SessionFile.write_conduction_area: unexpected net count");
return;
}
geometry.planar.Area curr_area = p_conduction_area.get_area();
int layer_no = p_conduction_area.get_layer();
board.Layer board_layer = p_board.layer_structure.arr[ layer_no];
Layer conduction_layer = new Layer(board_layer.name, layer_no, board_layer.is_signal);
geometry.planar.Shape boundary_shape;
geometry.planar.Shape [] holes;
if (curr_area instanceof geometry.planar.Shape)
{
boundary_shape = (geometry.planar.Shape) curr_area;
holes = new geometry.planar.Shape [0];
}
else
{
boundary_shape = curr_area.get_border();
holes = curr_area.get_holes();
}
p_file.start_scope();
p_file.write("wire ");
Shape dsn_shape = p_coordinate_transform.board_to_dsn(boundary_shape, conduction_layer);
if (dsn_shape != null)
{
dsn_shape.write_scope_int(p_file, p_identifier_type);
}
for (int i = 0; i < holes.length; ++i)
{
Shape dsn_hole = p_coordinate_transform.board_to_dsn(holes[i], conduction_layer);
dsn_hole.write_hole_scope(p_file, p_identifier_type);
}
p_file.end_scope();
}
}