Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
6418163d
Commit
6418163d
authored
Dec 02, 2011
by
Lorenzo Marcantonio
Committed by
Dick Hollenbeck
Dec 02, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update to the GENCAD import export
parent
05faa369
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
569 additions
and
425 deletions
+569
-425
class_pad.cpp
pcbnew/class_pad.cpp
+20
-10
export_gencad.cpp
pcbnew/export_gencad.cpp
+549
-415
No files found.
pcbnew/class_pad.cpp
View file @
6418163d
...
@@ -854,31 +854,41 @@ int D_PAD::Compare( const D_PAD* padref, const D_PAD* padcmp )
...
@@ -854,31 +854,41 @@ int D_PAD::Compare( const D_PAD* padref, const D_PAD* padcmp )
{
{
int
diff
;
int
diff
;
if
(
(
diff
=
padref
->
m_PadShape
-
padcmp
->
m_PadShape
)
)
if
(
diff
=
padref
->
m_PadShape
-
padcmp
->
m_PadShape
)
return
diff
;
return
diff
;
if
(
(
diff
=
padref
->
m_Size
.
x
-
padcmp
->
m_Size
.
x
)
)
if
(
diff
=
padref
->
m_DrillShape
-
padcmp
->
m_DrillShape
)
return
diff
;
return
diff
;
if
(
(
diff
=
padref
->
m_Size
.
y
-
padcmp
->
m_Size
.
y
)
)
if
(
diff
=
padref
->
m_Drill
.
x
-
padcmp
->
m_Drill
.
x
)
return
diff
;
return
diff
;
if
(
(
diff
=
padref
->
m_Offset
.
x
-
padcmp
->
m_Offset
.
x
)
)
if
(
diff
=
padref
->
m_Drill
.
y
-
padcmp
->
m_Drill
.
y
)
return
diff
;
return
diff
;
if
(
(
diff
=
padref
->
m_Offset
.
y
-
padcmp
->
m_Offset
.
y
)
)
if
(
diff
=
padref
->
m_Size
.
x
-
padcmp
->
m_Size
.
x
)
return
diff
;
return
diff
;
if
(
(
diff
=
padref
->
m_DeltaSize
.
x
-
padcmp
->
m_DeltaSize
.
x
)
)
if
(
diff
=
padref
->
m_Size
.
y
-
padcmp
->
m_Size
.
y
)
return
diff
;
return
diff
;
if
(
(
diff
=
padref
->
m_DeltaSize
.
y
-
padcmp
->
m_DeltaSize
.
y
)
)
if
(
diff
=
padref
->
m_Offset
.
x
-
padcmp
->
m_Offset
.
x
)
return
diff
;
if
(
diff
=
padref
->
m_Offset
.
y
-
padcmp
->
m_Offset
.
y
)
return
diff
;
if
(
diff
=
padref
->
m_DeltaSize
.
x
-
padcmp
->
m_DeltaSize
.
x
)
return
diff
;
if
(
diff
=
padref
->
m_DeltaSize
.
y
-
padcmp
->
m_DeltaSize
.
y
)
return
diff
;
return
diff
;
// @todo check if export_gencad still works:
// @todo check if export_gencad still works:
// specctra_export needs this, but maybe export_gencad does not. added on
// specctra_export needs this, but maybe export_gencad does not.
// Jan 24 2008 by Dick.
// Lorenzo: XXX no idea about specctra, but gencad need it to
if
(
(
diff
=
padref
->
m_layerMask
-
padcmp
->
m_layerMask
)
)
// implement padstacks!
if
(
diff
=
padref
->
m_layerMask
-
padcmp
->
m_layerMask
)
return
diff
;
return
diff
;
return
0
;
return
0
;
...
...
pcbnew/export_gencad.cpp
View file @
6418163d
...
@@ -46,55 +46,75 @@
...
@@ -46,55 +46,75 @@
#include "class_edge_mod.h"
#include "class_edge_mod.h"
bool
CreateHeaderInfoData
(
FILE
*
f
ile
,
PCB_EDIT_FRAME
*
frame
);
static
bool
CreateHeaderInfoData
(
FILE
*
aF
ile
,
PCB_EDIT_FRAME
*
frame
);
static
void
Create
TracksInfoData
(
FILE
*
file
,
BOARD
*
pcb
);
static
void
Create
ArtworksSection
(
FILE
*
aFile
);
static
void
Create
BoardSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
Create
TracksInfoData
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
Create
ComponentsSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
Create
BoardSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
Create
DevicesSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
Create
ComponentsSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
Create
RoutesSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
Create
DevicesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
Create
SignalsSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
Create
RoutesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
CreateS
hapesSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
CreateS
ignalsSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
Create
PadsShapesSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
Create
ShapesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
CreatePadsS
tacksSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
CreatePadsS
hapesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
FootprintWriteShape
(
FILE
*
File
,
MODULE
*
module
);
static
void
FootprintWriteShape
(
FILE
*
File
,
MODULE
*
module
);
// layer name for Gencad export
// layer name for Gencad export
static
const
wxString
GenCAD
_Layer_
Name
[
32
]
=
static
const
wxString
GenCAD
Layer
Name
[
32
]
=
{
{
wxT
(
"BOTTOM"
),
wxT
(
"INNER1"
),
wxT
(
"INNER2"
),
wxT
(
"BOTTOM"
),
wxT
(
"INNER1"
),
wxT
(
"INNER2"
),
wxT
(
"INNER3"
),
wxT
(
"INNER4"
),
wxT
(
"INNER5"
),
wxT
(
"INNER3"
),
wxT
(
"INNER4"
),
wxT
(
"INNER5"
),
wxT
(
"INNER6"
),
wxT
(
"INNER7"
),
wxT
(
"INNER8"
),
wxT
(
"INNER6"
),
wxT
(
"INNER7"
),
wxT
(
"INNER8"
),
wxT
(
"INNER9"
),
wxT
(
"INNER10"
),
wxT
(
"INNER11"
),
wxT
(
"INNER9"
),
wxT
(
"INNER10"
),
wxT
(
"INNER11"
),
wxT
(
"INNER12"
),
wxT
(
"INNER13"
),
wxT
(
"INNER14"
),
wxT
(
"INNER12"
),
wxT
(
"INNER13"
),
wxT
(
"INNER14"
),
wxT
(
"TOP"
),
wxT
(
"
adhecu"
),
wxT
(
"adhecmp
"
),
wxT
(
"TOP"
),
wxT
(
"
LAYER17"
),
wxT
(
"LAYER18
"
),
wxT
(
"SOLDERPASTE_BOTTOM"
),
wxT
(
"SOLDERPASTE_TOP"
),
wxT
(
"SOLDERPASTE_BOTTOM"
),
wxT
(
"SOLDERPASTE_TOP"
),
wxT
(
"SILKSCREEN_BOTTOM"
),
wxT
(
"SILKSCREEN_TOP"
),
wxT
(
"SILKSCREEN_BOTTOM"
),
wxT
(
"SILKSCREEN_TOP"
),
wxT
(
"SOLDERMASK_BOTTOM"
),
wxT
(
"SOLDERMASK_TOP"
),
wxT
(
"
drawings
"
),
wxT
(
"SOLDERMASK_BOTTOM"
),
wxT
(
"SOLDERMASK_TOP"
),
wxT
(
"
LAYER25
"
),
wxT
(
"
comments"
),
wxT
(
"eco1"
),
wxT
(
"eco2
"
),
wxT
(
"
LAYER26"
),
wxT
(
"LAYER27"
),
wxT
(
"LAYER28
"
),
wxT
(
"
edges"
),
wxT
(
"--"
),
wxT
(
"--
"
),
wxT
(
"
LAYER29"
),
wxT
(
"LAYER30"
),
wxT
(
"LAYER31
"
),
wxT
(
"
--
"
)
wxT
(
"
LAYER32
"
)
};
};
int
offsetX
,
offsetY
;
// flipped layer name for Gencad export (to make CAM350 imports correct)
D_PAD
*
PadList
;
static
const
wxString
GenCADLayerNameFlipped
[
32
]
=
{
wxT
(
"TOP"
),
wxT
(
"INNER14"
),
wxT
(
"INNER13"
),
wxT
(
"INNER12"
),
wxT
(
"INNER11"
),
wxT
(
"INNER10"
),
wxT
(
"INNER9"
),
wxT
(
"INNER8"
),
wxT
(
"INNER7"
),
wxT
(
"INNER6"
),
wxT
(
"INNER5"
),
wxT
(
"INNER4"
),
wxT
(
"INNER3"
),
wxT
(
"INNER2"
),
wxT
(
"INNER1"
),
wxT
(
"BOTTOM"
),
wxT
(
"LAYER17"
),
wxT
(
"LAYER18"
),
wxT
(
"SOLDERPASTE_TOP"
),
wxT
(
"SOLDERPASTE_BOTTOM"
),
wxT
(
"SILKSCREEN_TOP"
),
wxT
(
"SILKSCREEN_BOTTOM"
),
wxT
(
"SOLDERMASK_TOP"
),
wxT
(
"SOLDERMASK_BOTTOM"
),
wxT
(
"LAYER25"
),
wxT
(
"LAYER26"
),
wxT
(
"LAYER27"
),
wxT
(
"LAYER28"
),
wxT
(
"LAYER29"
),
wxT
(
"LAYER30"
),
wxT
(
"LAYER31"
),
wxT
(
"LAYER32"
)
};
// These are the export origin (the auxiliary axis)
static
int
GencadOffsetX
,
GencadOffsetY
;
/* GerbTool chokes on units different than INCH so this is the conversion
factor */
const
static
double
SCALE_FACTOR
=
10000.0
;
/*
2 helper functions to calculate coordinates of modules in gencad values (
/*
Two helper functions to calculate coordinates of modules in gencad values
* GenCAD Y axis from bottom to top)
*
(
GenCAD Y axis from bottom to top)
*/
*/
static
int
mapXto
(
int
x
)
static
double
MapXTo
(
int
aX
)
{
{
return
x
-
offsetX
;
return
(
aX
-
GencadOffsetX
)
/
SCALE_FACTOR
;
}
}
static
double
MapYTo
(
int
aY
)
static
int
mapYto
(
int
y
)
{
{
return
offsetY
-
y
;
return
(
GencadOffsetY
-
aY
)
/
SCALE_FACTOR
;
}
}
/* Driver function: processing starts here */
void
PCB_EDIT_FRAME
::
ExportToGenCAD
(
wxCommandEvent
&
e
vent
)
void
PCB_EDIT_FRAME
::
ExportToGenCAD
(
wxCommandEvent
&
aE
vent
)
{
{
wxFileName
fn
=
GetScreen
()
->
GetFileName
();
wxFileName
fn
=
GetScreen
()
->
GetFileName
();
wxString
msg
,
ext
,
wildcard
;
wxString
msg
,
ext
,
wildcard
;
...
@@ -117,11 +137,16 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
...
@@ -117,11 +137,16 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
DisplayError
(
this
,
msg
);
return
;
DisplayError
(
this
,
msg
);
return
;
}
}
/* Update some board data, to ensure a reliable gencad export: */
SetLocaleTo_C_standard
();
// No pesky decimal separators in gencad
// Update some board data, to ensure a reliable gencad export
GetBoard
()
->
ComputeBoundingBox
();
GetBoard
()
->
ComputeBoundingBox
();
offsetX
=
m_Auxiliary_Axis_Position
.
x
;
// Save the auxiliary origin for the rest of the module
offsetY
=
m_Auxiliary_Axis_Position
.
y
;
GencadOffsetX
=
m_Auxiliary_Axis_Position
.
x
;
GencadOffsetY
=
m_Auxiliary_Axis_Position
.
y
;
// No idea on *why* this should be needed... maybe to fix net names?
Compile_Ratsnest
(
NULL
,
true
);
Compile_Ratsnest
(
NULL
,
true
);
/* Temporary modification of footprints that are flipped (i.e. on bottom
/* Temporary modification of footprints that are flipped (i.e. on bottom
...
@@ -130,9 +155,10 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
...
@@ -130,9 +155,10 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
* that are given as normal orientation (non flipped, rotation = 0))
* that are given as normal orientation (non flipped, rotation = 0))
* these changes will be undone later
* these changes will be undone later
*/
*/
BOARD
*
pcb
=
GetBoard
();
MODULE
*
module
;
MODULE
*
module
;
for
(
module
=
GetBoard
()
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
for
(
module
=
pcb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
{
module
->
flag
=
0
;
module
->
flag
=
0
;
...
@@ -143,38 +169,33 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
...
@@ -143,38 +169,33 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
}
}
}
}
// Create file header:
/* Gencad has some mandatory and some optional sections: some importer
CreateHeaderInfoData
(
file
,
this
);
need the padstack section (which is optional) anyway. Also the
CreateBoardSection
(
file
,
GetBoard
()
);
order of the section *is* important */
/* Create TRACKS list
* This is the section $TRACK) (track width sizes) */
CreateTracksInfoData
(
file
,
GetBoard
()
);
/* Create the shapes list
CreateHeaderInfoData
(
file
,
this
);
// Gencad header
* (shapes of pads and footprints */
CreateBoardSection
(
file
,
pcb
);
// Board perimeter
CreatePadsShapesSection
(
file
,
GetBoard
()
);
/* Must be called
* before
* CreatePadsStacksSection
* and
* CreateShapesSection()
*/
CreatePadsStacksSection
(
file
,
GetBoard
()
);
CreateShapesSection
(
file
,
GetBoard
()
);
Create
DevicesSection
(
file
,
GetBoard
()
);
Create
PadsShapesSection
(
file
,
pcb
);
// Pads and padstacks
Create
ComponentsSection
(
file
,
GetBoard
()
);
Create
ArtworksSection
(
file
);
// Empty but mandatory
/* Create the list of Nets: */
/* Gencad splits a component info in shape, component and device.
CreateSignalsSection
(
file
,
GetBoard
()
);
We don't do any sharing (it would be difficult since each module is
customizable after placement) */
CreateShapesSection
(
file
,
pcb
);
CreateComponentsSection
(
file
,
pcb
);
CreateDevicesSection
(
file
,
pcb
);
// Creates the Routes section (i.e. the list of board tracks)
// In a similar way the netlist is split in net, track and route
CreateRoutesSection
(
file
,
GetBoard
()
);
CreateSignalsSection
(
file
,
pcb
);
CreateTracksInfoData
(
file
,
pcb
);
CreateRoutesSection
(
file
,
pcb
);
fclose
(
file
);
fclose
(
file
);
SetLocaleTo_Default
();
// revert to the current locale
/
* Undo the footprints modifications (flipped footprints) */
/
/ Undo the footprints modifications (flipped footprints)
for
(
module
=
GetBoard
()
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
for
(
module
=
pcb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
{
if
(
module
->
flag
)
if
(
module
->
flag
)
{
{
...
@@ -184,58 +205,96 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
...
@@ -184,58 +205,96 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
}
}
}
}
// Comparator for sorting pads with qsort
static
int
Pad
_list_Sort_by_Shapes
(
const
void
*
refptr
,
const
void
*
o
bjptr
)
static
int
Pad
ListSortByShape
(
const
void
*
aRefptr
,
const
void
*
aO
bjptr
)
{
{
const
D_PAD
*
padref
=
*
(
D_PAD
**
)
r
efptr
;
const
D_PAD
*
padref
=
*
(
D_PAD
**
)
aR
efptr
;
const
D_PAD
*
padcmp
=
*
(
D_PAD
**
)
o
bjptr
;
const
D_PAD
*
padcmp
=
*
(
D_PAD
**
)
aO
bjptr
;
return
D_PAD
::
Compare
(
padref
,
padcmp
);
return
D_PAD
::
Compare
(
padref
,
padcmp
);
}
}
// Sort vias for uniqueness
static
int
ViaSort
(
const
void
*
aRefptr
,
const
void
*
aObjptr
)
{
TRACK
*
padref
=
*
(
TRACK
**
)
aRefptr
;
TRACK
*
padcmp
=
*
(
TRACK
**
)
aObjptr
;
/* Creates the pads shapes list ( 1 shape per pad )
if
(
padref
->
m_Width
!=
padcmp
->
m_Width
)
* Uses .GetSubRatsnest member of class D_PAD, to handle the shape id (value 1
return
padref
->
m_Width
-
padcmp
->
m_Width
;
* ..n) for pads shapes PAD1 to PADn
*
if
(
padref
->
GetDrillValue
()
!=
padcmp
->
GetDrillValue
()
)
* The PADS section is used to describe the shape of all the pads used on the
return
padref
->
GetDrillValue
()
-
padcmp
->
GetDrillValue
();
* printed circuit board. The PADS section must be included, even if only a
* default pad is described and used for all pads.
if
(
padref
->
ReturnMaskLayer
()
!=
padcmp
->
ReturnMaskLayer
()
)
* The keywords used in the PADS section are:
return
padref
->
ReturnMaskLayer
()
-
padcmp
->
ReturnMaskLayer
();
* $PADS
* PAD <pad_name> <pad_type> <drill_size>
return
0
;
* LINE <line_ref>
}
* ARC <arc_ref>
* CIRCLE <circle_ref>
// The ARTWORKS section is empty but (officially) mandatory
* RECTANGLE <rectangle_ref>
static
void
CreateArtworksSection
(
FILE
*
aFile
)
* ATTRIBUTE <attrib_ref>
{
* $ENDPADS
/* The artworks section is empty */
* $PADS and $ENDPADS mark the PADS section of the GenCAD file. Each pad
fputs
(
"$ARTWORKS
\n
"
,
aFile
);
* description must start with a PAD keyword.
fputs
(
"$ENDARTWORKS
\n\n
"
,
aFile
);
* The layer in which a pad lies is defined in the SHAPE section of the GenCAD
}
* specification.
* The pad is always placed on a shape at the pad origin, or in a pad stack at
// Emit PADS and PADSTACKS. They are sorted and emitted uniquely.
* the pad stack origin.
// Via name is synthesized from their attributes, pads are numbered
*/
static
void
CreatePadsShapesSection
(
FILE
*
aFile
,
BOARD
*
aPcb
)
void
CreatePadsShapesSection
(
FILE
*
file
,
BOARD
*
pcb
)
{
{
std
::
vector
<
D_PAD
*>
pads
;
std
::
vector
<
D_PAD
*>
pads
;
std
::
vector
<
D_PAD
*>
padstacks
;
std
::
vector
<
TRACK
*>
vias
;
std
::
vector
<
TRACK
*>
viastacks
;
padstacks
.
resize
(
1
);
// We count pads from 1
const
char
*
pad_type
;
// The master layermask (i.e. the enabled layers) for padstack generation
unsigned
master_layermask
=
aPcb
->
GetBoardDesignSettings
()
->
GetEnabledLayers
();
fputs
(
"$PADS
\n
"
,
f
ile
);
fputs
(
"$PADS
\n
"
,
aF
ile
);
if
(
pcb
->
GetPadsCount
()
>
0
)
// Enumerate and sort the pads
if
(
aPcb
->
GetPadsCount
()
>
0
)
{
{
pads
.
insert
(
pads
.
end
(),
pads
.
insert
(
pads
.
end
(),
pcb
->
m_NetInfo
->
m_PadsFullList
.
begin
(),
aPcb
->
m_NetInfo
->
m_PadsFullList
.
begin
(),
pcb
->
m_NetInfo
->
m_PadsFullList
.
end
()
);
aPcb
->
m_NetInfo
->
m_PadsFullList
.
end
()
);
qsort
(
&
pads
[
0
],
pcb
->
GetPadsCount
(),
sizeof
(
D_PAD
*
),
Pad_list_Sort_by_Shapes
);
qsort
(
&
pads
[
0
],
aPcb
->
GetPadsCount
(),
sizeof
(
D_PAD
*
),
PadListSortByShape
);
}
}
D_PAD
*
old_pad
=
NULL
;
// The same for vias
int
pad_name_number
=
0
;
for
(
TRACK
*
track
=
aPcb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
if
(
track
->
Type
()
==
PCB_VIA_T
)
{
vias
.
push_back
(
track
);
}
}
qsort
(
&
vias
[
0
],
vias
.
size
(),
sizeof
(
TRACK
*
),
ViaSort
);
// Emit vias pads
TRACK
*
old_via
=
0
;
for
(
unsigned
i
=
0
;
i
<
vias
.
size
();
i
++
)
{
TRACK
*
via
=
vias
[
i
];
if
(
old_via
&&
0
==
ViaSort
(
&
old_via
,
&
via
))
continue
;
old_via
=
via
;
viastacks
.
push_back
(
via
);
fprintf
(
aFile
,
"PAD V%d.%d.%X ROUND %g
\n
CIRCLE 0 0 %g
\n
"
,
via
->
m_Width
,
via
->
GetDrillValue
(),
via
->
ReturnMaskLayer
(),
via
->
GetDrillValue
()
/
SCALE_FACTOR
,
via
->
m_Width
/
(
SCALE_FACTOR
*
2
)
);
}
// Emit component pads
D_PAD
*
old_pad
=
0
;
int
pad_name_number
=
0
;
for
(
unsigned
i
=
0
;
i
<
pads
.
size
();
++
i
)
for
(
unsigned
i
=
0
;
i
<
pads
.
size
();
++
i
)
{
{
D_PAD
*
pad
=
pads
[
i
];
D_PAD
*
pad
=
pads
[
i
];
...
@@ -250,8 +309,9 @@ void CreatePadsShapesSection( FILE* file, BOARD* pcb )
...
@@ -250,8 +309,9 @@ void CreatePadsShapesSection( FILE* file, BOARD* pcb )
pad_name_number
++
;
pad_name_number
++
;
pad
->
SetSubRatsnest
(
pad_name_number
);
pad
->
SetSubRatsnest
(
pad_name_number
);
fprintf
(
file
,
"PAD PAD
%d"
,
pad
->
GetSubRatsnest
()
);
fprintf
(
aFile
,
"PAD P
%d"
,
pad
->
GetSubRatsnest
()
);
padstacks
.
push_back
(
pad
);
// Will have its own padstack later
int
dx
=
pad
->
m_Size
.
x
/
2
;
int
dx
=
pad
->
m_Size
.
x
/
2
;
int
dy
=
pad
->
m_Size
.
y
/
2
;
int
dy
=
pad
->
m_Size
.
y
/
2
;
...
@@ -259,115 +319,169 @@ void CreatePadsShapesSection( FILE* file, BOARD* pcb )
...
@@ -259,115 +319,169 @@ void CreatePadsShapesSection( FILE* file, BOARD* pcb )
{
{
default
:
default
:
case
PAD_CIRCLE
:
case
PAD_CIRCLE
:
pad_type
=
"ROUND"
;
fprintf
(
aFile
,
" ROUND %g
\n
"
,
fprintf
(
file
,
" %s %d
\n
"
,
pad_type
,
pad
->
m_Drill
.
x
);
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
fprintf
(
file
,
"CIRCLE %d %d %d
\n
"
,
/* Circle is center, radius */
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
,
dx
);
fprintf
(
aFile
,
"CIRCLE %g %g %g
\n
"
,
pad
->
m_Offset
.
x
/
SCALE_FACTOR
,
-
pad
->
m_Offset
.
y
/
SCALE_FACTOR
,
pad
->
m_Size
.
x
/
(
SCALE_FACTOR
*
2
)
);
break
;
break
;
case
PAD_RECT
:
case
PAD_RECT
:
pad_type
=
"RECTANGULAR"
;
fprintf
(
aFile
,
" RECTANGULAR %g
\n
"
,
fprintf
(
file
,
" %s %d
\n
"
,
pad_type
,
pad
->
m_Drill
.
x
);
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
fprintf
(
file
,
"RECTANGLE %d %d %d %d
\n
"
,
// Rectangle is begin, size *not* begin, end!
pad
->
m_Offset
.
x
-
dx
,
-
pad
->
m_Offset
.
y
-
dy
,
fprintf
(
aFile
,
"RECTANGLE %g %g %g %g
\n
"
,
pad
->
m_Size
.
x
,
pad
->
m_Size
.
y
);
(
-
dx
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
dy
-
pad
->
m_Offset
.
y
)
/
SCALE_FACTOR
,
dx
/
(
SCALE_FACTOR
/
2
)
,
dy
/
(
SCALE_FACTOR
/
2
)
);
break
;
break
;
case
PAD_OVAL
:
/
* Create outline by 2 lines and 2 arcs */
case
PAD_OVAL
:
/
/ Create outline by 2 lines and 2 arcs
{
{
pad_type
=
"FINGER"
;
// OrCAD Layout call them OVAL or OBLONG - GenCAD call them FINGERs
fprintf
(
file
,
" %s %d
\n
"
,
pad_type
,
pad
->
m_Drill
.
x
);
fprintf
(
aFile
,
" FINGER %g
\n
"
,
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
int
dr
=
dx
-
dy
;
int
dr
=
dx
-
dy
;
if
(
dr
>=
0
)
// Horizontal oval
if
(
dr
>=
0
)
// Horizontal oval
{
{
int
radius
=
dy
;
int
radius
=
dy
;
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
-
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
radius
,
(
-
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
radius
);
(
-
pad
->
m_Offset
.
y
-
radius
)
/
SCALE_FACTOR
,
fprintf
(
file
,
"ARC %d %d %d %d %d %d
\n
"
,
(
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
radius
,
(
-
pad
->
m_Offset
.
y
-
radius
)
/
SCALE_FACTOR
);
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
radius
,
// GenCAD arcs are (start, end, center)
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
);
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
(
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
(
-
pad
->
m_Offset
.
y
-
radius
)
/
SCALE_FACTOR
,
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
radius
,
(
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
-
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
radius
);
(
-
pad
->
m_Offset
.
y
+
radius
)
/
SCALE_FACTOR
,
fprintf
(
file
,
"ARC %d %d %d %d %d %d
\n
"
,
(
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
-
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
radius
,
-
pad
->
m_Offset
.
y
/
SCALE_FACTOR
);
-
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
radius
,
-
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
);
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
(
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
radius
)
/
SCALE_FACTOR
,
(
-
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
radius
)
/
SCALE_FACTOR
);
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
(
-
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
radius
)
/
SCALE_FACTOR
,
(
-
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
radius
)
/
SCALE_FACTOR
,
(
-
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
-
pad
->
m_Offset
.
y
/
SCALE_FACTOR
);
}
}
else
// Vertical oval
else
// Vertical oval
{
{
dr
=
-
dr
;
dr
=
-
dr
;
int
radius
=
dx
;
int
radius
=
dx
;
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
-
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
dr
,
(
-
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
-
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
dr
);
(
-
pad
->
m_Offset
.
y
-
dr
)
/
SCALE_FACTOR
,
fprintf
(
file
,
"ARC %d %d %d %d %d %d
\n
"
,
(
-
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
-
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
dr
,
(
-
pad
->
m_Offset
.
y
+
dr
)
/
SCALE_FACTOR
);
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
dr
,
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
dr
);
(
-
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
dr
)
/
SCALE_FACTOR
,
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
(
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
dr
,
(
-
pad
->
m_Offset
.
y
+
dr
)
/
SCALE_FACTOR
,
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
dr
);
pad
->
m_Offset
.
x
/
SCALE_FACTOR
,
fprintf
(
file
,
"ARC %d %d %d %d %d %d
\n
"
,
(
-
pad
->
m_Offset
.
y
+
dr
)
/
SCALE_FACTOR
);
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
dr
,
-
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
dr
,
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
dr
);
(
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
dr
)
/
SCALE_FACTOR
,
(
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
dr
)
/
SCALE_FACTOR
);
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
(
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
dr
)
/
SCALE_FACTOR
,
(
-
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
dr
)
/
SCALE_FACTOR
,
pad
->
m_Offset
.
x
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
dr
)
/
SCALE_FACTOR
);
}
}
break
;
break
;
}
}
case
PAD_TRAPEZOID
:
case
PAD_TRAPEZOID
:
pad_type
=
"POLYGON"
;
fprintf
(
aFile
,
" POLYGON %g
\n
"
,
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
// XXX TO BE IMPLEMENTED! and I don't know if it could be actually imported by something
break
;
break
;
}
}
}
}
fputs
(
"
\n
$ENDPADS
\n\n
"
,
aFile
);
// Now emit the padstacks definitions, using the combined layer masks
fputs
(
"$PADSTACKS
\n
"
,
aFile
);
// Via padstacks
for
(
unsigned
i
=
0
;
i
<
viastacks
.
size
();
i
++
)
{
TRACK
*
via
=
viastacks
[
i
];
unsigned
mask
=
via
->
ReturnMaskLayer
()
&
master_layermask
;
fprintf
(
aFile
,
"PADSTACK VIA%d.%d.%X %g
\n
"
,
via
->
m_Width
,
via
->
GetDrillValue
(),
mask
,
via
->
GetDrillValue
()
/
SCALE_FACTOR
);
fputs
(
"$ENDPADS
\n\n
"
,
file
);
for
(
int
layer
=
0
;
layer
<
32
;
layer
++
)
{
if
(
mask
&
(
1
<<
layer
)
)
{
fprintf
(
aFile
,
"PAD V%d.%d.%X %s 0 0
\n
"
,
via
->
m_Width
,
via
->
GetDrillValue
(),
mask
,
TO_UTF8
(
GenCADLayerName
[
layer
])
);
}
}
}
}
/* Component padstacks
CAM350 don't apply correctly the FLIP semantics for padstacks, i.e. doesn't
swap the top and bottom layers... so I need to define the shape as MIRRORX
and define a separate 'flipped' padstack... until it appears yet another
noncompliant importer */
for
(
unsigned
i
=
1
;
i
<
padstacks
.
size
();
i
++
)
{
D_PAD
*
pad
=
padstacks
[
i
];
// Straight padstack
fprintf
(
aFile
,
"PADSTACK PAD%d %g
\n
"
,
i
,
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
for
(
int
layer
=
0
;
layer
<
32
;
layer
++
)
{
if
(
pad
->
m_layerMask
&
(
1
<<
layer
)
&
master_layermask
)
{
fprintf
(
aFile
,
"PAD P%d %s 0 0
\n
"
,
i
,
TO_UTF8
(
GenCADLayerName
[
layer
]
)
);
}
}
/*The PADSTACKS section is optional, and is used to describe how a group of
// Flipped padstack
* pads are
fprintf
(
aFile
,
"PADSTACK PAD%dF %g
\n
"
,
i
,
* arranged. The keywords used in the PADSTACKS section are:
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
* $PADSTACKS
for
(
int
layer
=
0
;
layer
<
32
;
layer
++
)
* PADSTACK <pad_name> <drill_size>
{
* PAD <pad_name> <layer> <rot> <mirror>
if
(
pad
->
m_layerMask
&
(
1
<<
layer
)
&
master_layermask
)
* ATTRIBUTE <attrib_ref>
* $ENDPADSTACKS
* $PADSTACKS and $ENDPADSTACKS mark the PADSTACKS section of the GenCAD file.
*/
void
CreatePadsStacksSection
(
FILE
*
file
,
BOARD
*
pcb
)
{
{
fputs
(
"$PADSTACKS
\n
"
,
file
);
fprintf
(
aFile
,
"PAD P%d %s 0 0
\n
"
,
i
,
fputs
(
"$ENDPADSTACKS
\n\n
"
,
file
);
TO_UTF8
(
GenCADLayerNameFlipped
[
layer
]
)
);
}
}
}
fputs
(
"$ENDPADSTACKS
\n\n
"
,
aFile
);
}
}
/* Creates the footprint shape list.
/* Creates the footprint shape list.
* We must use one shape for identical footprint (i.e. come from the same
* Since module shape is customizable after the placement we cannot share them;
* footprint in lib)
* instead we opt for the one-module-one-shape-one-component-one-device approach
* But because pads shapes and positions can be easily modified on board,
* a shape is created by footprint found.
* (todo : compare footprints shapes and creates only one shape for all
* footprints found having the same shape)
* The shape is always given in orientation 0, position 0 not flipped
*
* Syntax:
* $SHAPES
* SHAPE <shape_name>
* INSERT <string> here <string> = "TH"
* shape_descr (line, arc ..)
* PIN <pin_name> <pad_name> <x_y_ref> <layer> <rot> <mirror>
*
* SHAPE <shape_name>
* ..
* $ENDSHAPES
*/
*/
void
CreateShapesSection
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateShapesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
{
MODULE
*
module
;
MODULE
*
module
;
D_PAD
*
pad
;
D_PAD
*
pad
;
...
@@ -376,80 +490,73 @@ void CreateShapesSection( FILE* file, BOARD* pcb )
...
@@ -376,80 +490,73 @@ void CreateShapesSection( FILE* file, BOARD* pcb )
wxString
pinname
;
wxString
pinname
;
const
char
*
mirror
=
"0"
;
const
char
*
mirror
=
"0"
;
fputs
(
"$SHAPES
\n
"
,
f
ile
);
fputs
(
"$SHAPES
\n
"
,
aF
ile
);
for
(
module
=
p
cb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
for
(
module
=
aP
cb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
{
FootprintWriteShape
(
f
ile
,
module
);
FootprintWriteShape
(
aF
ile
,
module
);
for
(
pad
=
module
->
m_Pads
;
pad
!=
NULL
;
pad
=
pad
->
Next
()
)
for
(
pad
=
module
->
m_Pads
;
pad
!=
NULL
;
pad
=
pad
->
Next
()
)
{
{
/* Funny thing: GenCAD requires the pad side even if you use
padstacks (which are theorically optional but gerbtools
*requires* them). Now the trouble thing is that 'BOTTOM'
is interpreted by someone as a padstack flip even
if the spec explicitly says it's not... */
layer
=
"ALL"
;
layer
=
"ALL"
;
if
(
(
pad
->
m_layerMask
&
ALL_CU_LAYERS
)
==
LAYER_BACK
)
if
(
(
pad
->
m_layerMask
&
ALL_CU_LAYERS
)
==
LAYER_BACK
)
{
{
if
(
module
->
GetLayer
()
==
LAYER_N_FRONT
)
layer
=
(
module
->
flag
)
?
"TOP"
:
"BOTTOM"
;
layer
=
"BOTTOM"
;
else
layer
=
"TOP"
;
}
}
else
if
(
(
pad
->
m_layerMask
&
ALL_CU_LAYERS
)
==
LAYER_FRONT
)
else
if
(
(
pad
->
m_layerMask
&
ALL_CU_LAYERS
)
==
LAYER_FRONT
)
{
{
if
(
module
->
GetLayer
()
==
LAYER_N_FRONT
)
layer
=
(
module
->
flag
)
?
"BOTTOM"
:
"TOP"
;
layer
=
"TOP"
;
else
layer
=
"BOTTOM"
;
}
}
pad
->
ReturnStringPadName
(
pinname
);
pad
->
ReturnStringPadName
(
pinname
);
if
(
pinname
.
IsEmpty
()
)
if
(
pinname
.
IsEmpty
()
)
pinname
=
wxT
(
"non
am
e"
);
pinname
=
wxT
(
"none"
);
orient
=
pad
->
m_Orient
-
module
->
m_Orient
;
orient
=
pad
->
m_Orient
-
module
->
m_Orient
;
NORMALIZE_ANGLE_POS
(
orient
);
NORMALIZE_ANGLE_POS
(
orient
);
fprintf
(
file
,
"PIN %s PAD%d %d %d %s %d %s"
,
TO_UTF8
(
pinname
),
pad
->
GetSubRatsnest
(),
pad
->
m_Pos0
.
x
,
-
pad
->
m_Pos0
.
y
,
layer
,
orient
/
10
,
mirror
);
if
(
orient
%
10
)
fprintf
(
file
,
" .%d"
,
orient
%
10
);
fprintf
(
file
,
"
\n
"
);
// Bottom side modules use the flipped padstack
fprintf
(
aFile
,
(
module
->
flag
)
?
"PIN %s PAD%dF %g %g %s %g %s
\n
"
:
"PIN %s PAD%d %g %g %s %g %s
\n
"
,
TO_UTF8
(
pinname
),
pad
->
GetSubRatsnest
(),
pad
->
m_Pos0
.
x
/
SCALE_FACTOR
,
-
pad
->
m_Pos0
.
y
/
SCALE_FACTOR
,
layer
,
orient
/
10.0
,
mirror
);
}
}
}
}
fputs
(
"$ENDSHAPES
\n\n
"
,
f
ile
);
fputs
(
"$ENDSHAPES
\n\n
"
,
aF
ile
);
}
}
/* Creates the section $COMPONENTS (Footprints placement)
/* Creates the section $COMPONENTS (Footprints placement)
* When a footprint is on bottom side of the board::
* Bottom side components are difficult to handle: shapes must be mirrored or
* shapes are given with option "FLIP" and "MIRRORX".
* flipped, silk layers need to be handled correctly and so on. Also it seems
* - But shapes remain given like component not mirrored and not flipped
* that *noone* follows the specs...
* - orientation is given like if where not mirrored and not flipped.
*/
*/
void
CreateComponentsSection
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateComponentsSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
{
MODULE
*
module
=
pcb
->
m_Modules
;
TEXTE_MODULE
*
PtTexte
;
const
char
*
mirror
;
const
char
*
flip
;
int
ii
;
fputs
(
"$COMPONENTS
\n
"
,
f
ile
);
fputs
(
"$COMPONENTS
\n
"
,
aF
ile
);
for
(
;
module
!=
NULL
;
module
=
module
->
Next
()
)
for
(
MODULE
*
module
=
aPcb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
{
TEXTE_MODULE
*
textmod
;
const
char
*
mirror
;
const
char
*
flip
;
int
orient
=
module
->
m_Orient
;
int
orient
=
module
->
m_Orient
;
if
(
module
->
flag
)
if
(
module
->
flag
)
{
{
mirror
=
"MIRRORX"
;
// Mirrored relative to X axis
mirror
=
"0"
;
flip
=
"FLIP"
;
// Normal shape description ( gencad
flip
=
"FLIP"
;
// viewer must show it flipped and
// mirrored)
NEGATE_AND_NORMALIZE_ANGLE_POS
(
orient
);
NEGATE_AND_NORMALIZE_ANGLE_POS
(
orient
);
}
}
else
else
...
@@ -458,61 +565,61 @@ void CreateComponentsSection( FILE* file, BOARD* pcb )
...
@@ -458,61 +565,61 @@ void CreateComponentsSection( FILE* file, BOARD* pcb )
flip
=
"0"
;
flip
=
"0"
;
}
}
fprintf
(
file
,
"COMPONENT %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
aFile
,
"
\n
COMPONENT %s
\n
"
,
fprintf
(
file
,
"DEVICE %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
file
,
"PLACE %d %d
\n
"
,
mapXto
(
module
->
m_Pos
.
x
),
mapYto
(
module
->
m_Pos
.
y
)
);
fprintf
(
aFile
,
"DEVICE %s_%s
\n
"
,
fprintf
(
file
,
"LAYER %s
\n
"
,
(
module
->
flag
)
?
"BOTTOM"
:
"TOP"
);
TO_UTF8
(
module
->
m_Reference
->
m_Text
),
fprintf
(
file
,
"ROTATION %d"
,
orient
/
10
);
TO_UTF8
(
module
->
m_Value
->
m_Text
)
);
fprintf
(
aFile
,
"PLACE %g %g
\n
"
,
if
(
orient
%
10
)
MapXTo
(
module
->
m_Pos
.
x
),
fprintf
(
file
,
".%d"
,
orient
%
10
);
MapYTo
(
module
->
m_Pos
.
y
)
);
fprintf
(
aFile
,
"LAYER %s
\n
"
,
fputs
(
"
\n
"
,
file
);
(
module
->
flag
)
?
"BOTTOM"
:
"TOP"
);
fprintf
(
aFile
,
"ROTATION %g
\n
"
,
fprintf
(
file
,
"SHAPE %s %s %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
),
mirror
,
flip
);
orient
/
10.0
);
fprintf
(
aFile
,
"SHAPE %s %s %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
),
mirror
,
flip
);
/
* creates texts (ref and value) */
/
/ Text on silk layer: RefDes and value (are they actually useful?)
PtTexte
=
module
->
m_Reference
;
textmod
=
module
->
m_Reference
;
for
(
ii
=
0
;
ii
<
2
;
ii
++
)
for
(
i
nt
i
i
=
0
;
ii
<
2
;
ii
++
)
{
{
int
orient
=
PtTexte
->
m_Orient
;
int
orient
=
textmod
->
m_Orient
;
wxString
layer
=
GenCAD_Layer_Name
[
SILKSCREEN_N_FRONT
];
wxString
layer
=
GenCADLayerName
[(
module
->
flag
)
?
fprintf
(
file
,
"TEXT %d %d %d %d.%d %s %s
\"
%s
\"
"
,
SILKSCREEN_N_BACK
:
SILKSCREEN_N_FRONT
];
PtTexte
->
m_Pos0
.
x
,
-
PtTexte
->
m_Pos0
.
y
,
PtTexte
->
m_Size
.
x
,
fprintf
(
aFile
,
"TEXT %g %g %g %g %s %s
\"
%s
\"
"
,
orient
/
10
,
orient
%
10
,
textmod
->
m_Pos0
.
x
/
SCALE_FACTOR
,
-
textmod
->
m_Pos0
.
y
/
SCALE_FACTOR
,
textmod
->
m_Size
.
x
/
SCALE_FACTOR
,
orient
/
10.0
,
mirror
,
mirror
,
TO_UTF8
(
layer
),
TO_UTF8
(
layer
),
TO_UTF8
(
PtTexte
->
m_Text
)
TO_UTF8
(
textmod
->
m_Text
)
);
);
fprintf
(
file
,
" 0 0 %d %d
\n
"
,
// Please note, the width is approx
(
int
)
(
PtTexte
->
m_Size
.
x
*
PtTexte
->
m_Text
.
Len
()
),
fprintf
(
aFile
,
" 0 0 %g %g
\n
"
,
(
int
)
PtTexte
->
m_Size
.
y
);
(
textmod
->
m_Size
.
x
*
textmod
->
m_Text
.
Len
())
/
SCALE_FACTOR
,
textmod
->
m_Size
.
y
/
SCALE_FACTOR
);
PtTexte
=
module
->
m_Value
;
textmod
=
module
->
m_Value
;
// Dirty trick for the second iteration
}
}
//
put a comment:
//
The SHEET is a 'generic description' for referencing the component
fprintf
(
file
,
"SHEET Part %s %s
\n
"
,
fprintf
(
aFile
,
"SHEET
\"
RefDes: %s, Value: %s
\"
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
),
TO_UTF8
(
module
->
m_Reference
->
m_Text
),
TO_UTF8
(
module
->
m_Value
->
m_Text
)
);
TO_UTF8
(
module
->
m_Value
->
m_Text
)
);
}
}
fputs
(
"$ENDCOMPONENTS
\n\n
"
,
f
ile
);
fputs
(
"$ENDCOMPONENTS
\n\n
"
,
aF
ile
);
}
}
/* Emit the netlist (which is actually the thing for which GenCAD is used these
/* Creates the list of Nets:
* days!); tracks are handled later */
* $SIGNALS
static
void
CreateSignalsSection
(
FILE
*
aFile
,
BOARD
*
aPcb
)
* SIGNAL <net name>
* NODE <component name> <pin name>
* ...
* NODE <component name> <pin name>
* $ENDSIGNALS
*/
void
CreateSignalsSection
(
FILE
*
file
,
BOARD
*
pcb
)
{
{
wxString
msg
;
wxString
msg
;
NETINFO_ITEM
*
net
;
NETINFO_ITEM
*
net
;
...
@@ -520,11 +627,11 @@ void CreateSignalsSection( FILE* file, BOARD* pcb )
...
@@ -520,11 +627,11 @@ void CreateSignalsSection( FILE* file, BOARD* pcb )
MODULE
*
module
;
MODULE
*
module
;
int
NbNoConn
=
1
;
int
NbNoConn
=
1
;
fputs
(
"$SIGNALS
\n
"
,
f
ile
);
fputs
(
"$SIGNALS
\n
"
,
aF
ile
);
for
(
unsigned
ii
=
0
;
ii
<
p
cb
->
m_NetInfo
->
GetCount
();
ii
++
)
for
(
unsigned
ii
=
0
;
ii
<
aP
cb
->
m_NetInfo
->
GetCount
();
ii
++
)
{
{
net
=
p
cb
->
m_NetInfo
->
GetNetItem
(
ii
);
net
=
aP
cb
->
m_NetInfo
->
GetNetItem
(
ii
);
if
(
net
->
GetNetname
()
==
wxEmptyString
)
// dummy netlist (no connection)
if
(
net
->
GetNetname
()
==
wxEmptyString
)
// dummy netlist (no connection)
{
{
...
@@ -537,10 +644,10 @@ void CreateSignalsSection( FILE* file, BOARD* pcb )
...
@@ -537,10 +644,10 @@ void CreateSignalsSection( FILE* file, BOARD* pcb )
msg
=
wxT
(
"SIGNAL "
)
+
net
->
GetNetname
();
msg
=
wxT
(
"SIGNAL "
)
+
net
->
GetNetname
();
fputs
(
TO_UTF8
(
msg
),
f
ile
);
fputs
(
TO_UTF8
(
msg
),
aF
ile
);
fputs
(
"
\n
"
,
f
ile
);
fputs
(
"
\n
"
,
aF
ile
);
for
(
module
=
p
cb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
for
(
module
=
aP
cb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
{
for
(
pad
=
module
->
m_Pads
;
pad
!=
NULL
;
pad
=
pad
->
Next
()
)
for
(
pad
=
module
->
m_Pads
;
pad
!=
NULL
;
pad
=
pad
->
Next
()
)
{
{
...
@@ -550,53 +657,56 @@ void CreateSignalsSection( FILE* file, BOARD* pcb )
...
@@ -550,53 +657,56 @@ void CreateSignalsSection( FILE* file, BOARD* pcb )
continue
;
continue
;
pad
->
ReturnStringPadName
(
padname
);
pad
->
ReturnStringPadName
(
padname
);
msg
.
Printf
(
wxT
(
"NODE %s %
.4
s"
),
msg
.
Printf
(
wxT
(
"NODE %s %s"
),
GetChars
(
module
->
m_Reference
->
m_Text
),
GetChars
(
module
->
m_Reference
->
m_Text
),
GetChars
(
padname
)
);
GetChars
(
padname
)
);
fputs
(
TO_UTF8
(
msg
),
f
ile
);
fputs
(
TO_UTF8
(
msg
),
aF
ile
);
fputs
(
"
\n
"
,
f
ile
);
fputs
(
"
\n
"
,
aF
ile
);
}
}
}
}
}
}
fputs
(
"$ENDSIGNALS
\n\n
"
,
f
ile
);
fputs
(
"$ENDSIGNALS
\n\n
"
,
aF
ile
);
}
}
/* Creates the
section $HEADER ... $ENDHEADER
/* Creates the
header section; some of the data come from the frame
*/
*
(actually the screen), not from the pcb *
/
bool
CreateHeaderInfoData
(
FILE
*
file
,
PCB_EDIT_FRAME
*
f
rame
)
static
bool
CreateHeaderInfoData
(
FILE
*
aFile
,
PCB_EDIT_FRAME
*
aF
rame
)
{
{
wxString
msg
;
wxString
msg
;
PCB_SCREEN
*
screen
=
(
PCB_SCREEN
*
)
(
frame
->
GetScreen
()
);
PCB_SCREEN
*
screen
=
(
PCB_SCREEN
*
)
(
aFrame
->
GetScreen
()
);
fputs
(
"$HEADER
\n
"
,
file
);
fputs
(
"$HEADER
\n
"
,
aFile
);
fputs
(
"GENCAD 1.4
\n
"
,
file
);
fputs
(
"GENCAD 1.4
\n
"
,
aFile
);
msg
=
wxT
(
"USER "
)
+
wxGetApp
().
GetAppName
()
+
wxT
(
" "
)
+
GetBuildVersion
();
fputs
(
TO_UTF8
(
msg
),
file
);
fputs
(
"
\n
"
,
file
);
// Please note: GenCAD syntax requires quoted strings if they can contain spaces
msg
=
wxT
(
"DRAWING "
)
+
screen
->
GetFileName
();
msg
.
Printf
(
wxT
(
"USER
\"
%s %s
\"\n
"
),
fputs
(
TO_UTF8
(
msg
),
file
);
fputs
(
"
\n
"
,
file
);
GetChars
(
wxGetApp
().
GetAppName
()
),
msg
=
wxT
(
"REVISION "
)
+
screen
->
m_Revision
+
wxT
(
" "
)
+
screen
->
m_Date
;
GetChars
(
GetBuildVersion
()
)
);
fputs
(
TO_UTF8
(
msg
),
file
);
fputs
(
"
\n
"
,
file
);
fputs
(
TO_UTF8
(
msg
),
aFile
);
msg
.
Printf
(
wxT
(
"UNITS USER %d"
),
PCB_INTERNAL_UNIT
);
msg
=
wxT
(
"DRAWING
\"
"
)
+
screen
->
GetFileName
()
+
wxT
(
"
\"\n
"
);
fputs
(
TO_UTF8
(
msg
),
file
);
fputs
(
"
\n
"
,
file
);
fputs
(
TO_UTF8
(
msg
),
aFile
);
msg
.
Printf
(
wxT
(
"ORIGIN %d %d"
),
msg
=
wxT
(
"REVISION
\"
"
)
+
screen
->
m_Revision
+
wxT
(
" "
)
+
mapXto
(
frame
->
m_Auxiliary_Axis_Position
.
x
),
screen
->
m_Date
+
wxT
(
"
\"\n
"
);
mapYto
(
frame
->
m_Auxiliary_Axis_Position
.
y
)
);
fputs
(
TO_UTF8
(
msg
),
aFile
);
fputs
(
TO_UTF8
(
msg
),
file
);
fputs
(
"
\n
"
,
file
);
fputs
(
"UNITS INCH
\n
"
,
aFile
);
fputs
(
"INTERTRACK 0
\n
"
,
file
);
msg
.
Printf
(
wxT
(
"ORIGIN %g %g
\n
"
),
fputs
(
"$ENDHEADER
\n\n
"
,
file
);
MapXTo
(
aFrame
->
m_Auxiliary_Axis_Position
.
x
),
MapYTo
(
aFrame
->
m_Auxiliary_Axis_Position
.
y
)
);
fputs
(
TO_UTF8
(
msg
),
aFile
);
fputs
(
"INTERTRACK 0
\n
"
,
aFile
);
fputs
(
"$ENDHEADER
\n\n
"
,
aFile
);
return
true
;
return
true
;
}
}
/*
/*
* Sort function used to sort tracks segments:
* Sort function used to sort tracks segments:
* items are sorted by netcode, then by width then by layer
* items are sorted by netcode, then by width then by layer
*/
*/
static
int
Track
_list_Sort_by_
Netcode
(
const
void
*
refptr
,
const
void
*
objptr
)
static
int
Track
ListSortBy
Netcode
(
const
void
*
refptr
,
const
void
*
objptr
)
{
{
const
TRACK
*
ref
,
*
cmp
;
const
TRACK
*
ref
,
*
cmp
;
int
diff
;
int
diff
;
...
@@ -626,20 +736,21 @@ static int Track_list_Sort_by_Netcode( const void* refptr, const void* objptr )
...
@@ -626,20 +736,21 @@ static int Track_list_Sort_by_Netcode( const void* refptr, const void* objptr )
* $ENROUTE
* $ENROUTE
* Track segments must be sorted by nets
* Track segments must be sorted by nets
*/
*/
void
CreateRoutesSection
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateRoutesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
{
TRACK
*
track
,
**
tracklist
;
TRACK
*
track
,
**
tracklist
;
int
vianum
=
1
;
int
vianum
=
1
;
int
old_netcode
,
old_width
,
old_layer
;
int
old_netcode
,
old_width
,
old_layer
;
int
nbitems
,
ii
;
int
nbitems
,
ii
;
unsigned
master_layermask
=
aPcb
->
GetBoardDesignSettings
()
->
GetEnabledLayers
();
// Count items
// Count items
nbitems
=
0
;
nbitems
=
0
;
for
(
track
=
p
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
nbitems
++
;
nbitems
++
;
for
(
track
=
p
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
{
if
(
track
->
Type
()
==
PCB_ZONE_T
)
if
(
track
->
Type
()
==
PCB_ZONE_T
)
nbitems
++
;
nbitems
++
;
...
@@ -649,10 +760,10 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
...
@@ -649,10 +760,10 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
nbitems
=
0
;
nbitems
=
0
;
for
(
track
=
p
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
tracklist
[
nbitems
++
]
=
track
;
tracklist
[
nbitems
++
]
=
track
;
for
(
track
=
p
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
{
if
(
track
->
Type
()
==
PCB_ZONE_T
)
if
(
track
->
Type
()
==
PCB_ZONE_T
)
tracklist
[
nbitems
++
]
=
track
;
tracklist
[
nbitems
++
]
=
track
;
...
@@ -660,9 +771,9 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
...
@@ -660,9 +771,9 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
tracklist
[
nbitems
]
=
NULL
;
tracklist
[
nbitems
]
=
NULL
;
qsort
(
tracklist
,
nbitems
,
sizeof
(
TRACK
*
),
Track
_list_Sort_by_
Netcode
);
qsort
(
tracklist
,
nbitems
,
sizeof
(
TRACK
*
),
Track
ListSortBy
Netcode
);
fputs
(
"$ROUTES
\n
"
,
f
ile
);
fputs
(
"$ROUTES
\n
"
,
aF
ile
);
old_netcode
=
-
1
;
old_width
=
-
1
;
old_layer
=
-
1
;
old_netcode
=
-
1
;
old_width
=
-
1
;
old_layer
=
-
1
;
...
@@ -673,7 +784,7 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
...
@@ -673,7 +784,7 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
if
(
old_netcode
!=
track
->
GetNet
()
)
if
(
old_netcode
!=
track
->
GetNet
()
)
{
{
old_netcode
=
track
->
GetNet
();
old_netcode
=
track
->
GetNet
();
NETINFO_ITEM
*
net
=
p
cb
->
FindNet
(
track
->
GetNet
()
);
NETINFO_ITEM
*
net
=
aP
cb
->
FindNet
(
track
->
GetNet
()
);
wxString
netname
;
wxString
netname
;
if
(
net
&&
(
net
->
GetNetname
()
!=
wxEmptyString
)
)
if
(
net
&&
(
net
->
GetNetname
()
!=
wxEmptyString
)
)
...
@@ -681,13 +792,13 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
...
@@ -681,13 +792,13 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
else
else
netname
=
wxT
(
"_noname_"
);
netname
=
wxT
(
"_noname_"
);
fprintf
(
f
ile
,
"ROUTE %s
\n
"
,
TO_UTF8
(
netname
)
);
fprintf
(
aF
ile
,
"ROUTE %s
\n
"
,
TO_UTF8
(
netname
)
);
}
}
if
(
old_width
!=
track
->
m_Width
)
if
(
old_width
!=
track
->
m_Width
)
{
{
old_width
=
track
->
m_Width
;
old_width
=
track
->
m_Width
;
fprintf
(
f
ile
,
"TRACK TRACK%d
\n
"
,
track
->
m_Width
);
fprintf
(
aF
ile
,
"TRACK TRACK%d
\n
"
,
track
->
m_Width
);
}
}
if
(
(
track
->
Type
()
==
PCB_TRACE_T
)
||
(
track
->
Type
()
==
PCB_ZONE_T
)
)
if
(
(
track
->
Type
()
==
PCB_TRACE_T
)
||
(
track
->
Type
()
==
PCB_ZONE_T
)
)
...
@@ -695,24 +806,25 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
...
@@ -695,24 +806,25 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
if
(
old_layer
!=
track
->
GetLayer
()
)
if
(
old_layer
!=
track
->
GetLayer
()
)
{
{
old_layer
=
track
->
GetLayer
();
old_layer
=
track
->
GetLayer
();
fprintf
(
f
ile
,
"LAYER %s
\n
"
,
fprintf
(
aF
ile
,
"LAYER %s
\n
"
,
TO_UTF8
(
GenCAD
_Layer_
Name
[
track
->
GetLayer
()
&
0x1F
]
)
);
TO_UTF8
(
GenCAD
Layer
Name
[
track
->
GetLayer
()
&
0x1F
]
)
);
}
}
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
mapXto
(
track
->
m_Start
.
x
),
mapYt
o
(
track
->
m_Start
.
y
),
MapXTo
(
track
->
m_Start
.
x
),
MapYT
o
(
track
->
m_Start
.
y
),
mapXto
(
track
->
m_End
.
x
),
mapYt
o
(
track
->
m_End
.
y
)
);
MapXTo
(
track
->
m_End
.
x
),
MapYT
o
(
track
->
m_End
.
y
)
);
}
}
if
(
track
->
Type
()
==
PCB_VIA_T
)
if
(
track
->
Type
()
==
PCB_VIA_T
)
{
{
fprintf
(
file
,
"VIA viapad%d %d %d ALL %d via%d
\n
"
,
fprintf
(
aFile
,
"VIA VIA%d.%d.%X %g %g ALL %g via%d
\n
"
,
track
->
m_Width
,
track
->
m_Width
,
track
->
GetDrillValue
(),
mapXto
(
track
->
m_Start
.
x
),
mapYto
(
track
->
m_Start
.
y
),
track
->
ReturnMaskLayer
()
&
master_layermask
,
track
->
GetDrillValue
(),
vianum
++
);
MapXTo
(
track
->
m_Start
.
x
),
MapYTo
(
track
->
m_Start
.
y
),
track
->
GetDrillValue
()
/
SCALE_FACTOR
,
vianum
++
);
}
}
}
}
fputs
(
"$ENDROUTES
\n\n
"
,
f
ile
);
fputs
(
"$ENDROUTES
\n\n
"
,
aF
ile
);
delete
tracklist
;
delete
tracklist
;
}
}
...
@@ -722,64 +834,54 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
...
@@ -722,64 +834,54 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
* This is a list of footprints properties
* This is a list of footprints properties
* ( Shapes are in section $SHAPE )
* ( Shapes are in section $SHAPE )
*/
*/
void
CreateDevicesSection
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateDevicesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
{
MODULE
*
module
;
MODULE
*
module
;
D_PAD
*
pad
;
fputs
(
"$DEVICES
\n
"
,
file
);
fputs
(
"$DEVICES
\n
"
,
aFile
);
for
(
module
=
pcb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
fprintf
(
file
,
"DEVICE %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
file
,
"PART %s
\n
"
,
TO_UTF8
(
module
->
m_LibRef
)
);
fprintf
(
file
,
"TYPE %s
\n
"
,
"UNKNOWN"
);
for
(
pad
=
module
->
m_Pads
;
pad
!=
NULL
;
pad
=
pad
->
Next
()
)
for
(
module
=
aPcb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
{
fprintf
(
file
,
"PINDESCR %.4s"
,
pad
->
m_Padname
);
fprintf
(
aFile
,
"DEVICE
\"
%s
\"\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
aFile
,
"PART
\"
%s
\"\n
"
,
TO_UTF8
(
module
->
m_Value
->
m_Text
)
);
if
(
pad
->
GetNetname
()
==
wxEmptyString
)
fprintf
(
aFile
,
"PACKAGE
\"
%s
\"\n
"
,
TO_UTF8
(
module
->
m_LibRef
)
);
fputs
(
" NoConn
\n
"
,
file
);
// The TYPE attribute is almost freeform
else
const
char
*
ty
=
"TH"
;
fprintf
(
file
,
" %.4s
\n
"
,
pad
->
m_Padname
);
if
(
module
->
m_Attributs
&
MOD_CMS
)
}
ty
=
"SMD"
;
if
(
module
->
m_Attributs
&
MOD_VIRTUAL
)
fprintf
(
file
,
"ATTRIBUTE %s
\n
"
,
TO_UTF8
(
module
->
m_Value
->
m_Text
)
);
ty
=
"VIRTUAL"
;
fprintf
(
aFile
,
"TYPE %s
\n
"
,
ty
);
}
}
fputs
(
"$ENDDEVICES
\n\n
"
,
f
ile
);
fputs
(
"$ENDDEVICES
\n\n
"
,
aF
ile
);
}
}
/* Creates the section $BOARD.
/* Creates the section $BOARD.
* We output here only the board
boundary box
* We output here only the board
perimeter
*/
*/
void
CreateBoardSection
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateBoardSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
{
fputs
(
"$BOARD
\n
"
,
file
);
fputs
(
"$BOARD
\n
"
,
aFile
);
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
// Extract the board edges
mapXto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
x
),
for
(
EDA_ITEM
*
drawing
=
aPcb
->
m_Drawings
;
mapYto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
y
),
drawing
!=
0
;
mapXto
(
pcb
->
m_BoundaryBox
.
GetRight
()
),
drawing
=
drawing
->
Next
()
)
mapYto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
y
)
);
{
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
if
(
drawing
->
Type
()
==
PCB_LINE_T
)
mapXto
(
pcb
->
m_BoundaryBox
.
GetRight
()
),
{
mapYto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
y
),
DRAWSEGMENT
*
drawseg
=
dynamic_cast
<
DRAWSEGMENT
*>
(
drawing
);
mapXto
(
pcb
->
m_BoundaryBox
.
GetRight
()
),
if
(
drawseg
->
GetLayer
()
==
EDGE_N
)
mapYto
(
pcb
->
m_BoundaryBox
.
GetBottom
()
)
);
{
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
// XXX GenCAD supports arc boundaries but I've seen nothing that reads them
mapXto
(
pcb
->
m_BoundaryBox
.
GetRight
()
),
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
mapYto
(
pcb
->
m_BoundaryBox
.
GetBottom
()
),
MapXTo
(
drawseg
->
m_Start
.
x
),
MapYTo
(
drawseg
->
m_Start
.
y
),
mapXto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
x
),
MapXTo
(
drawseg
->
m_End
.
x
),
MapYTo
(
drawseg
->
m_End
.
y
));
mapYto
(
pcb
->
m_BoundaryBox
.
GetBottom
()
)
);
}
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
}
mapXto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
x
),
}
mapYto
(
pcb
->
m_BoundaryBox
.
GetBottom
()
),
fputs
(
"$ENDBOARD
\n\n
"
,
aFile
);
mapXto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
x
),
mapYto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
y
)
);
fputs
(
"$ENDBOARD
\n\n
"
,
file
);
}
}
...
@@ -793,18 +895,19 @@ void CreateBoardSection( FILE* file, BOARD* pcb )
...
@@ -793,18 +895,19 @@ void CreateBoardSection( FILE* file, BOARD* pcb )
* Each tool name is build like this: "TRACK" + track width.
* Each tool name is build like this: "TRACK" + track width.
* For instance for a width = 120 : name = "TRACK120".
* For instance for a width = 120 : name = "TRACK120".
*/
*/
void
CreateTracksInfoData
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateTracksInfoData
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
{
TRACK
*
track
;
TRACK
*
track
;
int
last_width
=
-
1
;
int
last_width
=
-
1
;
/* Find thickness used for traces. */
// Find thickness used for traces
// XXX could use the same sorting approach used for pads
std
::
vector
<
int
>
trackinfo
;
std
::
vector
<
int
>
trackinfo
;
unsigned
ii
;
unsigned
ii
;
for
(
track
=
p
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
{
if
(
last_width
!=
track
->
m_Width
)
// Find a thickness already used.
if
(
last_width
!=
track
->
m_Width
)
// Find a thickness already used.
{
{
...
@@ -821,7 +924,7 @@ void CreateTracksInfoData( FILE* file, BOARD* pcb )
...
@@ -821,7 +924,7 @@ void CreateTracksInfoData( FILE* file, BOARD* pcb )
}
}
}
}
for
(
track
=
p
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
{
if
(
last_width
!=
track
->
m_Width
)
// Find a thickness already used.
if
(
last_width
!=
track
->
m_Width
)
// Find a thickness already used.
{
{
...
@@ -839,116 +942,147 @@ void CreateTracksInfoData( FILE* file, BOARD* pcb )
...
@@ -839,116 +942,147 @@ void CreateTracksInfoData( FILE* file, BOARD* pcb )
}
}
// Write data
// Write data
fputs
(
"$TRACKS
\n
"
,
f
ile
);
fputs
(
"$TRACKS
\n
"
,
aF
ile
);
for
(
ii
=
0
;
ii
<
trackinfo
.
size
();
ii
++
)
for
(
ii
=
0
;
ii
<
trackinfo
.
size
();
ii
++
)
{
{
fprintf
(
file
,
"TRACK TRACK%d %d
\n
"
,
trackinfo
[
ii
],
trackinfo
[
ii
]
);
fprintf
(
aFile
,
"TRACK TRACK%d %g
\n
"
,
trackinfo
[
ii
],
trackinfo
[
ii
]
/
SCALE_FACTOR
);
}
}
fputs
(
"$ENDTRACKS
\n\n
"
,
f
ile
);
fputs
(
"$ENDTRACKS
\n\n
"
,
aF
ile
);
}
}
/* Creates the shape of a footprint (section SHAPE)
/* Creates the shape of a footprint (section SHAPE)
* The shape is always given "normal" (Orient 0, not mirrored)
* The shape is always given "normal" (Orient 0, not mirrored)
* Syntax:
* It's almost guaranteed that the silk layer will be imported wrong but
* SHAPE <shape_name>
* the shape also contains the pads!
* INSERT <string> here <string> = "TH"
* shape_descr (line, arc ..):
* LINE startX startY endX endY
* ARC startX startY endX endY centreX centreY
* PAD_CIRCLE centreX scentreY radius
*/
*/
void
FootprintWriteShape
(
FILE
*
f
ile
,
MODULE
*
module
)
static
void
FootprintWriteShape
(
FILE
*
aF
ile
,
MODULE
*
module
)
{
{
EDGE_MODULE
*
edge
;
EDGE_MODULE
*
PtEdge
;
EDA_ITEM
*
item
;
EDA_ITEM
*
PtStruct
;
int
y_axis_sign
=
-
1
;
// Control Y axis change sign (as normal
// Control Y axis change sign for flipped modules
// module / mirror axis and conventions)
int
Yaxis_sign
=
-
1
;
// Flip for bottom side components
if
(
module
->
flag
)
Yaxis_sign
=
1
;
/* creates header: */
/* creates header: */
fprintf
(
file
,
"SHAPE %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
aFile
,
"
\n
SHAPE %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
file
,
"INSERT %s
\n
"
,
(
module
->
m_Attributs
&
MOD_CMS
)
?
"SMD"
:
"TH"
);
if
(
module
->
m_Attributs
&
MOD_VIRTUAL
)
{
fprintf
(
aFile
,
"INSERT SMD
\n
"
);
}
else
{
if
(
module
->
m_Attributs
&
MOD_CMS
)
{
fprintf
(
aFile
,
"INSERT SMD
\n
"
);
}
else
{
fprintf
(
aFile
,
"INSERT TH
\n
"
);
}
}
#if 0 /* ATTRIBUTE name and value is unspecified and the original exporter
* got the syntax wrong, so CAM350 rejected the whole shape! */
/* creates Attributes */
if( module->m_Attributs != MOD_DEFAULT )
if( module->m_Attributs != MOD_DEFAULT )
{
{
fprintf
(
f
ile
,
"ATTRIBUTE"
);
fprintf(
aF
ile, "ATTRIBUTE" );
if( module->m_Attributs & MOD_CMS )
if( module->m_Attributs & MOD_CMS )
fprintf
(
f
ile
,
" PAD_SMD"
);
fprintf(
aF
ile, " PAD_SMD" );
if( module->m_Attributs & MOD_VIRTUAL )
if( module->m_Attributs & MOD_VIRTUAL )
fprintf
(
f
ile
,
" VIRTUAL"
);
fprintf(
aF
ile, " VIRTUAL" );
fprintf
(
f
ile
,
"
\n
"
);
fprintf(
aF
ile, "\n" );
}
}
#endif
/* creates Drawing */
// Silk outline; wildly interpreted by various importers:
item
=
module
->
m_Drawings
;
// CAM350 read it right but only closed shapes
// ProntoPlace double-flip it (at least the pads are correct)
for
(
;
item
!=
NULL
;
item
=
item
->
Next
()
)
// GerberTool usually get it right...
for
(
PtStruct
=
module
->
m_Drawings
;
PtStruct
!=
NULL
;
PtStruct
=
PtStruct
->
Next
()
)
{
{
switch
(
item
->
Type
()
)
switch
(
PtStruct
->
Type
()
)
{
{
case
PCB_MODULE_TEXT_T
:
case
PCB_MODULE_TEXT_T
:
// If we wanted to export text, this is not the correct section
break
;
break
;
case
PCB_MODULE_EDGE_T
:
case
PCB_MODULE_EDGE_T
:
edge
=
(
EDGE_MODULE
*
)
item
;
PtEdge
=
(
EDGE_MODULE
*
)
PtStruct
;
if
(
PtEdge
->
GetLayer
()
==
SILKSCREEN_N_FRONT
switch
(
edge
->
m_Shape
)
||
PtEdge
->
GetLayer
()
==
SILKSCREEN_N_BACK
)
{
switch
(
PtEdge
->
m_Shape
)
{
{
case
S_SEGMENT
:
case
S_SEGMENT
:
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
edge
->
m_Start0
.
x
,
y_axis_sign
*
edge
->
m_Start0
.
y
,
(
PtEdge
->
m_Start0
.
x
)
/
SCALE_FACTOR
,
edge
->
m_End0
.
x
,
y_axis_sign
*
edge
->
m_End0
.
y
);
(
Yaxis_sign
*
PtEdge
->
m_Start0
.
y
)
/
SCALE_FACTOR
,
(
PtEdge
->
m_End0
.
x
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
PtEdge
->
m_End0
.
y
)
/
SCALE_FACTOR
);
break
;
break
;
case
S_CIRCLE
:
case
S_CIRCLE
:
{
{
int
radius
=
(
int
)
hypot
(
(
double
)
(
edge
->
m_End0
.
x
-
edge
->
m_Start0
.
x
),
int
radius
=
(
int
)
hypot
(
(
double
)
(
edge
->
m_End0
.
y
-
edge
->
m_Start0
.
y
)
);
(
double
)
(
PtEdge
->
m_End0
.
x
-
PtEdge
->
m_Start0
.
x
),
fprintf
(
file
,
"CIRCLE %d %d %d
\n
"
,
(
double
)
(
PtEdge
->
m_End0
.
y
-
PtEdge
->
m_Start0
.
y
)
);
edge
->
m_Start0
.
x
,
y_axis_sign
*
edge
->
m_Start0
.
y
,
radius
);
fprintf
(
aFile
,
"CIRCLE %g %g %g
\n
"
,
PtEdge
->
m_Start0
.
x
/
SCALE_FACTOR
,
Yaxis_sign
*
PtEdge
->
m_Start0
.
y
/
SCALE_FACTOR
,
radius
/
SCALE_FACTOR
);
break
;
break
;
}
}
case
S_ARC
:
/* print ARC x,y start x,y end x,y center */
case
S_ARC
:
{
// Arcs are defined counter clockwise (positive trigonometric)
{
// from the start point to the end point (0 to 360 degrees)
int
arcendx
,
arcendy
;
wxPoint
arcStart
,
arcEnd
;
arcendx
=
PtEdge
->
m_End0
.
x
-
PtEdge
->
m_Start0
.
x
;
arcendy
=
PtEdge
->
m_End0
.
y
-
PtEdge
->
m_Start0
.
y
;
// edge->m_Start0 is the arc center relative to the shape position
RotatePoint
(
&
arcendx
,
&
arcendy
,
-
PtEdge
->
m_Angle
);
// edge->m_End0 is the arc start point relative to the shape position
arcendx
+=
PtEdge
->
m_Start0
.
x
;
arcStart
=
edge
->
m_End0
;
arcendy
+=
PtEdge
->
m_Start0
.
y
;
if
(
Yaxis_sign
==
-
1
)
{
// calculate arcEnd arc end point relative to the shape position, in Pcbnew
// Flipping Y flips the arc direction too
// coordinates
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
arcEnd
=
arcStart
;
(
arcendx
)
/
SCALE_FACTOR
,
RotatePoint
(
&
arcEnd
,
edge
->
m_Start0
,
-
edge
->
m_Angle
);
(
Yaxis_sign
*
arcendy
)
/
SCALE_FACTOR
,
(
PtEdge
->
m_End0
.
x
)
/
SCALE_FACTOR
,
// due to difference between Pcbnew and gencad, swap arc start and arc end
(
Yaxis_sign
*
PtEdge
->
m_End0
.
y
)
/
SCALE_FACTOR
,
EXCHG
(
arcEnd
,
arcStart
);
(
PtEdge
->
m_Start0
.
x
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
PtEdge
->
m_Start0
.
y
)
/
SCALE_FACTOR
);
// print arc shape:
}
else
{
fprintf
(
file
,
"ARC %d %d %d %d %d %d
\n
"
,
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
arcStart
.
x
,
y_axis_sign
*
arcStart
.
y
,
// Start point
(
PtEdge
->
m_End0
.
x
)
/
SCALE_FACTOR
,
arcEnd
.
x
,
y_axis_sign
*
arcEnd
.
y
,
// End point
(
Yaxis_sign
*
PtEdge
->
m_End0
.
y
)
/
SCALE_FACTOR
,
edge
->
m_Start0
.
x
,
y_axis_sign
*
edge
->
m_Start0
.
y
);
(
arcendx
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
arcendy
)
/
SCALE_FACTOR
,
(
PtEdge
->
m_Start0
.
x
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
PtEdge
->
m_Start0
.
y
)
/
SCALE_FACTOR
);
}
break
;
break
;
}
}
default
:
default
:
DisplayError
(
NULL
,
wxT
(
"Type Edge Module invalid."
)
);
DisplayError
(
NULL
,
wxT
(
"Type Edge Module invalid."
)
);
break
;
break
;
}
/* end switch PtEdge->m_Shape */
}
}
break
;
break
;
default
:
default
:
break
;
break
;
}
/* End switch Items type */
}
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment