1096 lines
38 KiB
C++
1096 lines
38 KiB
C++
/*******************************************************/
|
||
/* Module de generation de la Netliste , selon Formats */
|
||
/*******************************************************/
|
||
|
||
#include "fctsys.h"
|
||
#include "gr_basic.h"
|
||
|
||
#include "common.h"
|
||
#include "program.h"
|
||
#include "libcmp.h"
|
||
#include "general.h"
|
||
#include "netlist.h"
|
||
|
||
#include "protos.h"
|
||
|
||
|
||
/* Routines locales */
|
||
static void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& FullFileName );
|
||
static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f,
|
||
bool with_pcbnew );
|
||
static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f );
|
||
static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet );
|
||
static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_netnames );
|
||
|
||
static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet );
|
||
static void AddPinToComponentPinList( EDA_SchComponentStruct* Component,
|
||
LibDrawPin* PinEntry );
|
||
static void FindOthersUnits( EDA_SchComponentStruct* Component );
|
||
static int SortPinsByNum( ObjetNetListStruct** Pin1, ObjetNetListStruct** Pin2 );
|
||
static void EraseDuplicatePins( ObjetNetListStruct** TabPin, int NbrPin );
|
||
|
||
static void ClearUsedFlags( WinEDA_SchematicFrame* frame );
|
||
|
||
|
||
/* Variable locales */
|
||
static int s_SortedPinCount;
|
||
static ObjetNetListStruct** s_SortedComponentPinList;
|
||
|
||
|
||
/******************************************************************************/
|
||
void WriteNetList( WinEDA_SchematicFrame* frame, const wxString& FileNameNL,
|
||
bool use_netnames )
|
||
/*******************************************************************************/
|
||
|
||
/* Create the netlist file ( Format is given by g_NetFormat )
|
||
* bool use_netnames is used only for Spice netlist
|
||
*/
|
||
{
|
||
FILE* f = NULL;
|
||
|
||
if( g_NetFormat < NET_TYPE_CUSTOM1 )
|
||
{
|
||
if( ( f = wxFopen( FileNameNL, wxT( "wt" ) ) ) == NULL )
|
||
{
|
||
wxString msg = _( "Failed to create file " ) + FileNameNL;
|
||
DisplayError( frame, msg );
|
||
return;
|
||
}
|
||
}
|
||
|
||
wxBusyCursor Busy;
|
||
|
||
switch( g_NetFormat )
|
||
{
|
||
case NET_TYPE_PCBNEW:
|
||
WriteNetListPCBNEW( frame, f, TRUE );
|
||
fclose( f );
|
||
break;
|
||
|
||
case NET_TYPE_ORCADPCB2:
|
||
WriteNetListPCBNEW( frame, f, FALSE );
|
||
fclose( f );
|
||
break;
|
||
|
||
case NET_TYPE_CADSTAR:
|
||
WriteNetListCADSTAR( frame, f );
|
||
fclose( f );
|
||
break;
|
||
|
||
case NET_TYPE_SPICE:
|
||
WriteNetListPspice( frame, f, use_netnames );
|
||
fclose( f );
|
||
break;
|
||
|
||
default:
|
||
Write_GENERIC_NetList( frame, FileNameNL );
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
/****************************************************************************/
|
||
static EDA_SchComponentStruct* FindNextComponentAndCreatPinList(
|
||
EDA_BaseStruct* DrawList )
|
||
/****************************************************************************/
|
||
|
||
/* Find a "suitable" component from the DrawList
|
||
* build its pin list s_SortedComponentPinList.
|
||
* The list is sorted by pin num
|
||
* A suitable component is a "new" real component (power symbols are not considered)
|
||
*
|
||
* alloc memory for s_SortedComponentPinList if s_SortedComponentPinList == NULL
|
||
* Must be deallocated by the user
|
||
*/
|
||
{
|
||
EDA_SchComponentStruct* Component = NULL;
|
||
EDA_LibComponentStruct* Entry;
|
||
LibEDA_BaseStruct* DEntry;
|
||
|
||
s_SortedPinCount = 0;
|
||
|
||
for( ; DrawList != NULL; DrawList = DrawList->Next() )
|
||
{
|
||
if( DrawList->Type() != DRAW_LIB_ITEM_STRUCT_TYPE )
|
||
continue;
|
||
Component = (EDA_SchComponentStruct*) DrawList;
|
||
|
||
/* already tested ? : */
|
||
if( Component->m_FlagControlMulti == 1 )
|
||
continue; /* yes */
|
||
|
||
Entry = FindLibPart( Component->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
|
||
if( Entry == NULL )
|
||
continue;
|
||
|
||
/* Power symbol and other component which have the reference starting by
|
||
* "#" are not included in netlist (pseudo components) */
|
||
if( Component->m_Field[REFERENCE].m_Text[0] == '#' )
|
||
continue;
|
||
|
||
/* Create the pin table for this component */
|
||
int ii = sizeof(ObjetNetListStruct) * MAXPIN;
|
||
if( s_SortedComponentPinList == NULL )
|
||
s_SortedComponentPinList = (ObjetNetListStruct**) MyMalloc( ii );
|
||
memset( s_SortedComponentPinList, 0, ii );
|
||
|
||
DEntry = Entry->m_Drawings;
|
||
for( ; DEntry != NULL; DEntry = DEntry->Next() )
|
||
{
|
||
if( DEntry->Type() != COMPONENT_PIN_DRAW_TYPE )
|
||
continue;
|
||
if( DEntry->m_Unit
|
||
&& (DEntry->m_Unit != Component->m_Multi) )
|
||
continue;
|
||
if( DEntry->m_Convert
|
||
&& (DEntry->m_Convert != Component->m_Convert) )
|
||
continue;
|
||
{
|
||
AddPinToComponentPinList( Component, (LibDrawPin*) DEntry );
|
||
}
|
||
}
|
||
|
||
Component->m_FlagControlMulti = 1;
|
||
|
||
if( Entry->m_UnitCount > 1 )
|
||
FindOthersUnits( Component );
|
||
|
||
/* Tri sur le numero de Pin de TabListePin */
|
||
qsort( s_SortedComponentPinList, s_SortedPinCount, sizeof(ObjetNetListStruct*),
|
||
( int( * ) ( const void*, const void* ) )SortPinsByNum );
|
||
|
||
/* Elimination des Pins redondantes du s_SortedComponentPinList */
|
||
EraseDuplicatePins( s_SortedComponentPinList, s_SortedPinCount );
|
||
|
||
return Component;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
/**************************************************************************************/
|
||
static wxString ReturnPinNetName( ObjetNetListStruct* Pin,
|
||
const wxString& DefaultFormatNetname )
|
||
/**************************************************************************************/
|
||
|
||
/* Return the net name for the pin Pin.
|
||
* Net name is:
|
||
* "?" if pin not connected
|
||
* "netname" for global net (like gnd, vcc ..
|
||
* "netname_sheetnumber" for the usual nets
|
||
*/
|
||
{
|
||
int netcode = Pin->GetNet();
|
||
wxString NetName;
|
||
|
||
if( (netcode == 0 ) || ( Pin->m_FlagOfConnection != PAD_CONNECT ) )
|
||
{
|
||
return NetName;
|
||
}
|
||
else
|
||
{
|
||
int jj;
|
||
for( jj = 0; jj < g_NbrObjNet; jj++ )
|
||
{
|
||
if( g_TabObjNet[jj].GetNet() != netcode )
|
||
continue;
|
||
if( ( g_TabObjNet[jj].m_Type != NET_GLOBLABEL)
|
||
&& ( g_TabObjNet[jj].m_Type != NET_LABEL)
|
||
&& ( g_TabObjNet[jj].m_Type != NET_PINLABEL) )
|
||
continue;
|
||
|
||
NetName = *g_TabObjNet[jj].m_Label;
|
||
break;
|
||
}
|
||
|
||
if( !NetName.IsEmpty() )
|
||
{
|
||
if( g_TabObjNet[jj].m_Type != NET_PINLABEL )
|
||
NetName << wxT( "_" ) << g_TabObjNet[jj].m_SheetNumber;
|
||
}
|
||
else
|
||
{
|
||
NetName.Printf( DefaultFormatNetname.GetData(), netcode );
|
||
}
|
||
}
|
||
return NetName;
|
||
}
|
||
|
||
|
||
/***********************************************************************/
|
||
void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame,
|
||
const wxString& FullFileName )
|
||
/***********************************************************************/
|
||
|
||
/* Create a generic netlist, and call an external netlister
|
||
* to change the netlist syntax and create the file
|
||
*/
|
||
{
|
||
wxString Line, FootprintName;
|
||
BASE_SCREEN* CurrScreen;
|
||
EDA_BaseStruct* DrawList;
|
||
EDA_SchComponentStruct* Component;
|
||
wxString netname;
|
||
int ii;
|
||
FILE* tmpfile;
|
||
wxString TmpFullFileName = FullFileName;
|
||
|
||
ChangeFileNameExt( TmpFullFileName, wxT( ".tmp" ) );
|
||
|
||
if( ( tmpfile = wxFopen( TmpFullFileName, wxT( "wt" ) ) ) == NULL )
|
||
{
|
||
wxString msg = _( "Failed to create file " ) + TmpFullFileName;
|
||
DisplayError( frame, msg );
|
||
return;
|
||
}
|
||
|
||
ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/
|
||
fprintf( tmpfile, "$BeginNetlist\n" );
|
||
|
||
/* Create netlist module section */
|
||
fprintf( tmpfile, "$BeginComponentList\n" );
|
||
EDA_ScreenList ScreenList( NULL );
|
||
for( CurrScreen = ScreenList.GetFirst(); CurrScreen != NULL; CurrScreen = ScreenList.GetNext() )
|
||
{
|
||
for( DrawList = CurrScreen->EEDrawList; DrawList != NULL; DrawList = DrawList->Pnext )
|
||
{
|
||
DrawList = Component = FindNextComponentAndCreatPinList( DrawList );
|
||
if( Component == NULL )
|
||
break; // No component left
|
||
|
||
FootprintName.Empty();
|
||
if( !Component->m_Field[FOOTPRINT].IsVoid() )
|
||
{
|
||
FootprintName = Component->m_Field[FOOTPRINT].m_Text;
|
||
FootprintName.Replace( wxT( " " ), wxT( "_" ) );
|
||
}
|
||
|
||
fprintf( tmpfile, "\n$BeginComponent\n" );
|
||
fprintf( tmpfile, "TimeStamp=%8.8lX\n", Component->m_TimeStamp );
|
||
fprintf( tmpfile, "Footprint=%s\n", CONV_TO_UTF8( FootprintName ) );
|
||
Line = wxT( "Reference=" ) + Component->m_Field[REFERENCE].m_Text + wxT( "\n" );
|
||
Line.Replace( wxT( " " ), wxT( "_" ) );
|
||
fprintf( tmpfile, CONV_TO_UTF8( Line ) );
|
||
|
||
Line = Component->m_Field[VALUE].m_Text;
|
||
Line.Replace( wxT( " " ), wxT( "_" ) );
|
||
fprintf( tmpfile, "Value=%s\n", CONV_TO_UTF8( Line ) );
|
||
|
||
Line = Component->m_ChipName;
|
||
Line.Replace( wxT( " " ), wxT( "_" ) );
|
||
fprintf( tmpfile, "Libref=%s\n", CONV_TO_UTF8( Line ) );
|
||
|
||
// Write pin list:
|
||
fprintf( tmpfile, "$BeginPinList\n" );
|
||
for( ii = 0; ii < s_SortedPinCount; ii++ )
|
||
{
|
||
ObjetNetListStruct* Pin = s_SortedComponentPinList[ii];
|
||
if( !Pin )
|
||
continue;
|
||
netname = ReturnPinNetName( Pin, wxT( "$-%.6d" ) );
|
||
if( netname.IsEmpty() )
|
||
netname = wxT( "?" );
|
||
fprintf( tmpfile, "%.4s=%s\n", (char*) &Pin->m_PinNum,
|
||
CONV_TO_UTF8( netname ) );
|
||
}
|
||
|
||
fprintf( tmpfile, "$EndPinList\n" );
|
||
fprintf( tmpfile, "$EndComponent\n" );
|
||
}
|
||
}
|
||
|
||
MyFree( s_SortedComponentPinList );
|
||
s_SortedComponentPinList = NULL;
|
||
|
||
fprintf( tmpfile, "$EndComponentList\n" );
|
||
|
||
fprintf( tmpfile, "\n$BeginNets\n" );
|
||
WriteGENERICListOfNets( tmpfile, g_TabObjNet );
|
||
fprintf( tmpfile, "$EndNets\n" );
|
||
fprintf( tmpfile, "\n$EndNetlist\n" );
|
||
fclose( tmpfile );
|
||
|
||
// Call the external module (plug in )
|
||
|
||
if( g_NetListerCommandLine.IsEmpty() )
|
||
return;
|
||
|
||
wxString CommandFile;
|
||
if( wxIsAbsolutePath( g_NetListerCommandLine ) )
|
||
CommandFile = g_NetListerCommandLine;
|
||
else
|
||
CommandFile = FindKicadFile( g_NetListerCommandLine );
|
||
|
||
CommandFile += wxT( " " ) + TmpFullFileName;
|
||
CommandFile += wxT( " " ) + FullFileName;
|
||
|
||
wxExecute( CommandFile, wxEXEC_SYNC );
|
||
}
|
||
|
||
|
||
/********************************************************/
|
||
static void ClearUsedFlags( WinEDA_SchematicFrame* frame )
|
||
/********************************************************/
|
||
/* Clear flag FlagControlMulti, used in netlist generation */
|
||
{
|
||
SCH_SCREEN* screen;
|
||
EDA_BaseStruct* DrawList;
|
||
|
||
EDA_ScreenList ScreenList( NULL );
|
||
|
||
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
|
||
{
|
||
DrawList = screen->EEDrawList;
|
||
while( DrawList )
|
||
{
|
||
if( DrawList->Type() == DRAW_LIB_ITEM_STRUCT_TYPE )
|
||
{
|
||
EDA_SchComponentStruct* Component = (EDA_SchComponentStruct*) DrawList;
|
||
Component->m_FlagControlMulti = 0;
|
||
}
|
||
DrawList = DrawList->Pnext;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************/
|
||
static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f,
|
||
bool use_netnames )
|
||
/*************************************************************/
|
||
|
||
/* Routine de generation du fichier netliste ( Format PSPICE )
|
||
* si use_netnames = TRUE
|
||
* les nodes sont identifies par le netname
|
||
* sinon les nodes sont identifies par le netnumber
|
||
*
|
||
* tous les textes graphiques commen<65>ant par [.-+]pspice ou [.-+]gnucap
|
||
* sont consid<69>r<EFBFBD>s comme des commandes a placer dans la netliste
|
||
* [.-]pspice ou gnucap sont en debut
|
||
+pspice et +gnucap sont en fin de netliste
|
||
*/
|
||
{
|
||
char Line[1024];
|
||
SCH_SCREEN* screen;
|
||
EDA_BaseStruct* DrawList;
|
||
EDA_SchComponentStruct* Component;
|
||
int ii, nbitems;
|
||
wxString text;
|
||
wxArrayString SpiceCommandAtBeginFile, SpiceCommandAtEndFile;
|
||
wxString msg;
|
||
|
||
#define BUFYPOS_LEN 4
|
||
wxChar bufnum[BUFYPOS_LEN + 1];
|
||
|
||
DateAndTime( Line );
|
||
fprintf( f, "* %s (Spice format) creation date: %s\n\n", NETLIST_HEAD_STRING, Line );
|
||
|
||
/* Create text list starting by [.-]pspice , or [.-]gnucap (simulator commands) */
|
||
/* and create text list starting by [+]pspice , or [+]gnucap (simulator commands) */
|
||
bufnum[BUFYPOS_LEN] = 0;
|
||
EDA_ScreenList ScreenList( NULL );
|
||
|
||
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
|
||
{
|
||
for( DrawList = screen->EEDrawList; DrawList != NULL; DrawList = DrawList->Pnext )
|
||
{
|
||
wxChar ident;
|
||
if( DrawList->Type() != DRAW_TEXT_STRUCT_TYPE )
|
||
continue;
|
||
#define DRAWTEXT ( (DrawTextStruct*) DrawList )
|
||
text = DRAWTEXT->m_Text; if( text.IsEmpty() )
|
||
continue;
|
||
ident = text.GetChar( 0 );
|
||
if( ident != '.' && ident != '-' && ident != '+' )
|
||
continue;
|
||
text.Remove( 0, 1 ); //Remove the first char.
|
||
text.Remove( 6 ); //text contains 6 char.
|
||
if( ( text == wxT( "pspice" ) ) || ( text == wxT( "gnucap" ) ) )
|
||
{
|
||
/* Put the Y position as an ascii string, for sort by vertical position,
|
||
* using usual sort string by alphabetic value */
|
||
int ypos = DRAWTEXT->m_Pos.y;
|
||
for( ii = 0; ii < BUFYPOS_LEN; ii++ )
|
||
{
|
||
bufnum[BUFYPOS_LEN - 1 - ii] = (ypos & 63) + ' '; ypos >>= 6;
|
||
}
|
||
|
||
text = DRAWTEXT->m_Text.AfterFirst( ' ' );
|
||
msg.Printf( wxT( "%s %s" ), bufnum, text.GetData() ); // First BUFYPOS_LEN char are the Y position
|
||
if( ident == '+' )
|
||
SpiceCommandAtEndFile.Add( msg );
|
||
else
|
||
SpiceCommandAtBeginFile.Add( msg );
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Print texts starting by [.-]pspice , ou [.-]gnucap (of course, without the Y position string)*/
|
||
nbitems = SpiceCommandAtBeginFile.GetCount();
|
||
if( nbitems )
|
||
{
|
||
SpiceCommandAtBeginFile.Sort();
|
||
for( ii = 0; ii < nbitems; ii++ )
|
||
{
|
||
SpiceCommandAtBeginFile[ii].Remove( 0, BUFYPOS_LEN );
|
||
SpiceCommandAtBeginFile[ii].Trim( TRUE );
|
||
SpiceCommandAtBeginFile[ii].Trim( FALSE );
|
||
fprintf( f, "%s\n", CONV_TO_UTF8( SpiceCommandAtBeginFile[ii] ) );
|
||
}
|
||
}
|
||
fprintf( f, "\n" );
|
||
|
||
|
||
/* Create component list */
|
||
ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/
|
||
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
|
||
{
|
||
for( DrawList = screen->EEDrawList; DrawList != NULL; DrawList = DrawList->Pnext )
|
||
{
|
||
DrawList = Component = FindNextComponentAndCreatPinList( DrawList );
|
||
if( Component == NULL )
|
||
break;
|
||
|
||
fprintf( f, "%s ", CONV_TO_UTF8( Component->m_Field[REFERENCE].m_Text ) );
|
||
|
||
// Write pin list:
|
||
for( ii = 0; ii < s_SortedPinCount; ii++ )
|
||
{
|
||
ObjetNetListStruct* Pin = s_SortedComponentPinList[ii];
|
||
if( !Pin )
|
||
continue;
|
||
wxString NetName = ReturnPinNetName( Pin, wxT( "N-%.6d" ) );
|
||
if( NetName.IsEmpty() )
|
||
NetName = wxT( "?" );
|
||
if( use_netnames )
|
||
fprintf( f, " %s", CONV_TO_UTF8( NetName ) );
|
||
else // Use number for net names (with net number = 0 for "GND"
|
||
{
|
||
// NetName = "0" is "GND" net for Spice
|
||
if( NetName == wxT( "0" ) || NetName == wxT( "GND" ) )
|
||
fprintf( f, " 0" );
|
||
else
|
||
fprintf( f, " %d", Pin->GetNet() );
|
||
}
|
||
}
|
||
|
||
fprintf( f, " %s\n", CONV_TO_UTF8( Component->m_Field[VALUE].m_Text ) );
|
||
}
|
||
}
|
||
|
||
MyFree( s_SortedComponentPinList );
|
||
s_SortedComponentPinList = NULL;
|
||
|
||
/* Print texts starting by [+]pspice , ou [+]gnucap */
|
||
nbitems = SpiceCommandAtEndFile.GetCount();
|
||
if( nbitems )
|
||
{
|
||
fprintf( f, "\n" );
|
||
SpiceCommandAtEndFile.Sort();
|
||
for( ii = 0; ii < nbitems; ii++ )
|
||
{
|
||
SpiceCommandAtEndFile[ii].Remove( 0, +BUFYPOS_LEN );
|
||
SpiceCommandAtEndFile[ii].Trim( TRUE );
|
||
SpiceCommandAtEndFile[ii].Trim( FALSE );
|
||
fprintf( f, "%s\n", CONV_TO_UTF8( SpiceCommandAtEndFile[ii] ) );
|
||
}
|
||
}
|
||
|
||
fprintf( f, "\n.end\n" );
|
||
}
|
||
|
||
|
||
/*****************************************************************************************/
|
||
static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew )
|
||
/*****************************************************************************************/
|
||
|
||
/* Routine de generation du fichier netliste ( Format ORCAD PCB 2 ameliore )
|
||
* si with_pcbnew = FALSE
|
||
* format PCBNEW (OrcadPcb2 + commentaires et liste des nets)
|
||
* si with_pcbnew = FALSE
|
||
* Format ORCADPCB2 strict
|
||
*/
|
||
{
|
||
wxString Line, FootprintName;
|
||
char Buf[256];
|
||
SCH_SCREEN* CurrScreen;
|
||
EDA_BaseStruct* DrawList;
|
||
EDA_SchComponentStruct* Component;
|
||
int ii;
|
||
EDA_SchComponentStruct** CmpList = NULL;
|
||
int CmpListCount = 0, CmpListSize = 1000;
|
||
|
||
DateAndTime( Buf );
|
||
if( with_pcbnew )
|
||
fprintf( f, "# %s created %s\n(\n", NETLIST_HEAD_STRING, Buf );
|
||
else
|
||
fprintf( f, "( { %s created %s }\n", NETLIST_HEAD_STRING, Buf );
|
||
|
||
|
||
/* Create netlist module section */
|
||
ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/
|
||
|
||
EDA_ScreenList ScreenList( NULL );
|
||
|
||
for( CurrScreen = ScreenList.GetFirst(); CurrScreen != NULL; CurrScreen = ScreenList.GetNext() )
|
||
{
|
||
for( DrawList = CurrScreen->EEDrawList; DrawList != NULL; DrawList = DrawList->Pnext )
|
||
{
|
||
DrawList = Component = FindNextComponentAndCreatPinList( DrawList );
|
||
if( Component == NULL )
|
||
break;
|
||
|
||
/* Get the Component FootprintFilter and put the component in CmpList if filter is not void */
|
||
EDA_LibComponentStruct* Entry;
|
||
if( ( Entry = FindLibPart( Component->m_ChipName.GetData(), wxEmptyString,
|
||
FIND_ROOT ) ) != NULL )
|
||
{
|
||
if( Entry->m_FootprintList.GetCount() != 0 ) /* Put in list */
|
||
{
|
||
if( CmpList == NULL )
|
||
CmpList = (EDA_SchComponentStruct**) MyZMalloc( sizeof(
|
||
EDA_SchComponentStruct
|
||
*) * CmpListSize );
|
||
if( CmpListCount >= CmpListSize )
|
||
{
|
||
CmpListSize += 1000;
|
||
CmpList = (EDA_SchComponentStruct**) realloc(
|
||
CmpList,
|
||
sizeof(
|
||
EDA_SchComponentStruct*)
|
||
* CmpListSize );
|
||
}
|
||
CmpList[CmpListCount] = Component;
|
||
CmpListCount++;
|
||
}
|
||
}
|
||
|
||
if( !Component->m_Field[FOOTPRINT].IsVoid() )
|
||
{
|
||
FootprintName = Component->m_Field[FOOTPRINT].m_Text;
|
||
FootprintName.Replace( wxT( " " ), wxT( "_" ) );
|
||
}
|
||
else
|
||
FootprintName = wxT( "$noname" );
|
||
|
||
Line = Component->m_Field[REFERENCE].m_Text;
|
||
Line.Replace( wxT( " " ), wxT( "_" ) );
|
||
fprintf( f, " ( %8.8lX %s",
|
||
Component->m_TimeStamp,
|
||
CONV_TO_UTF8( FootprintName ) );
|
||
fprintf( f, " %s", CONV_TO_UTF8( Line ) );
|
||
|
||
Line = Component->m_Field[VALUE].m_Text;
|
||
Line.Replace( wxT( " " ), wxT( "_" ) );
|
||
fprintf( f, " %s", CONV_TO_UTF8( Line ) );
|
||
|
||
if( with_pcbnew ) // Add the lib name for this component
|
||
{
|
||
Line = Component->m_ChipName;
|
||
Line.Replace( wxT( " " ), wxT( "_" ) );
|
||
fprintf( f, " {Lib=%s}", CONV_TO_UTF8( Line ) );
|
||
}
|
||
fprintf( f, "\n" );
|
||
|
||
// Write pin list:
|
||
for( ii = 0; ii < s_SortedPinCount; ii++ )
|
||
{
|
||
ObjetNetListStruct* Pin = s_SortedComponentPinList[ii];
|
||
if( !Pin )
|
||
continue;
|
||
wxString netname = ReturnPinNetName( Pin, wxT( "N-%.6d" ) );
|
||
if( netname.IsEmpty() )
|
||
netname = wxT( " ?" );
|
||
fprintf( f, " ( %4.4s %s )\n", (char*) &Pin->m_PinNum,
|
||
CONV_TO_UTF8( netname ) );
|
||
}
|
||
|
||
fprintf( f, " )\n" );
|
||
}
|
||
}
|
||
|
||
fprintf( f, ")\n*\n" );
|
||
|
||
MyFree( s_SortedComponentPinList );
|
||
s_SortedComponentPinList = NULL;
|
||
|
||
/* Write the allowed footprint list for each component */
|
||
if( with_pcbnew && CmpList )
|
||
{
|
||
fprintf( f, "{ Allowed footprints by component:\n" );
|
||
EDA_LibComponentStruct* Entry;
|
||
for( ii = 0; ii < CmpListCount; ii++ )
|
||
{
|
||
Component = CmpList[ii];
|
||
Entry = FindLibPart( Component->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
|
||
Line = Component->m_Field[REFERENCE].m_Text;
|
||
Line.Replace( wxT( " " ), wxT( "_" ) );
|
||
fprintf( f, "$component %s\n", CONV_TO_UTF8( Line ) );
|
||
/* Write the footprint list */
|
||
for( unsigned int jj = 0; jj < Entry->m_FootprintList.GetCount(); jj++ )
|
||
{
|
||
fprintf( f, " %s\n", CONV_TO_UTF8( Entry->m_FootprintList[jj] ) );
|
||
}
|
||
|
||
fprintf( f, "$endlist\n" );
|
||
}
|
||
|
||
fprintf( f, "$endfootprintlist\n}\n" );
|
||
}
|
||
if( CmpList )
|
||
free( CmpList );
|
||
|
||
if( with_pcbnew )
|
||
{
|
||
fprintf( f, "{ Pin List by Nets\n" );
|
||
WriteGENERICListOfNets( f, g_TabObjNet );
|
||
fprintf( f, "}\n" );
|
||
fprintf( f, "#End\n" );
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************************************/
|
||
static void AddPinToComponentPinList( EDA_SchComponentStruct* Component, LibDrawPin* Pin )
|
||
/*************************************************************************************/
|
||
|
||
/* Add a new pin description in the pin list s_SortedComponentPinList
|
||
* a pin description is a pointer to the corresponding structure
|
||
* created by BuildNetList() in the table g_TabObjNet
|
||
*/
|
||
{
|
||
int ii;
|
||
|
||
/* Search the PIN description for Pin in g_TabObjNet*/
|
||
for( ii = 0; ii < g_NbrObjNet; ii++ )
|
||
{
|
||
if( g_TabObjNet[ii].m_Type != NET_PIN )
|
||
continue;
|
||
if( g_TabObjNet[ii].m_Link != Component )
|
||
continue;
|
||
if( g_TabObjNet[ii].m_PinNum != Pin->m_PinNum )
|
||
continue;
|
||
{
|
||
s_SortedComponentPinList[s_SortedPinCount] = &g_TabObjNet[ii];
|
||
s_SortedPinCount++;
|
||
if( s_SortedPinCount >= MAXPIN )
|
||
{
|
||
/* Log message for Internal error */
|
||
DisplayError( NULL, wxT( "AddPinToComponentPinList err: MAXPIN reached" ) );
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/**********************************************************************/
|
||
static void EraseDuplicatePins( ObjetNetListStruct** TabPin, int NbrPin )
|
||
/**********************************************************************/
|
||
|
||
/*
|
||
* Routine qui elimine les Pins de meme Numero de la liste des objets
|
||
* (Liste des Pins d'un boitier) passee en entree
|
||
* Ces pins redondantes proviennent des pins (alims... ) communes a plusieurs
|
||
* elements d'un boitier a multiple parts.
|
||
*/
|
||
{
|
||
int ii, jj;
|
||
|
||
for( ii = 0; ii < NbrPin - 1; ii++ )
|
||
{
|
||
if( TabPin[ii] == NULL )
|
||
continue; /* Deja supprime */
|
||
if( TabPin[ii]->m_PinNum != TabPin[ii + 1]->m_PinNum )
|
||
continue;
|
||
/* 2 Pins doublees */
|
||
for( jj = ii + 1; jj < NbrPin; jj++ )
|
||
{
|
||
if( TabPin[ii]->m_PinNum != TabPin[jj]->m_PinNum )
|
||
break;
|
||
TabPin[jj] = NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/**********************************************************************/
|
||
static void FindOthersUnits( EDA_SchComponentStruct* Component )
|
||
/**********************************************************************/
|
||
|
||
/* Recherche les autres parts du boitier auquel appartient la part Component,
|
||
* pour les boitiers a parts multiples.
|
||
* Appelle AddPinToComponentPinList() pour classer les pins des parts trouvees
|
||
*/
|
||
{
|
||
EDA_BaseStruct* DrawList;
|
||
EDA_SchComponentStruct* Component2;
|
||
EDA_LibComponentStruct* Entry;
|
||
LibEDA_BaseStruct* DEntry;
|
||
SCH_SCREEN* screen;
|
||
|
||
EDA_ScreenList ScreenList( NULL );
|
||
|
||
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
|
||
{
|
||
DrawList = screen->EEDrawList;
|
||
while( DrawList )
|
||
{
|
||
switch( DrawList->Type() )
|
||
{
|
||
case DRAW_LIB_ITEM_STRUCT_TYPE:
|
||
Component2 = (EDA_SchComponentStruct*) DrawList;
|
||
|
||
if( Component2->m_FlagControlMulti == 1 )
|
||
break;
|
||
|
||
if( Component2->m_Field[REFERENCE].m_Text.CmpNoCase(
|
||
Component->m_Field[REFERENCE].m_Text ) != 0 )
|
||
break;
|
||
|
||
Entry = FindLibPart( Component2->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
|
||
if( Entry == NULL )
|
||
break;
|
||
if( Component2->m_Field[REFERENCE].m_Text[0] == '#' )
|
||
break;
|
||
|
||
if( Entry->m_Drawings != NULL )
|
||
{
|
||
DEntry = Entry->m_Drawings;
|
||
for( ; DEntry != NULL; DEntry = DEntry->Next() )
|
||
{
|
||
if( DEntry->Type() != COMPONENT_PIN_DRAW_TYPE )
|
||
continue;
|
||
if( DEntry->m_Unit
|
||
&& (DEntry->m_Unit != Component2->m_Multi) )
|
||
continue;
|
||
if( DEntry->m_Convert
|
||
&& (DEntry->m_Convert != Component2->m_Convert) )
|
||
continue;
|
||
{
|
||
AddPinToComponentPinList( Component2, (LibDrawPin*) DEntry );
|
||
}
|
||
}
|
||
}
|
||
Component2->m_FlagControlMulti = 1;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
DrawList = DrawList->Pnext;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/**************************************************************************/
|
||
static int SortPinsByNum( ObjetNetListStruct** Pin1, ObjetNetListStruct** Pin2 )
|
||
/**************************************************************************/
|
||
|
||
/* Routine de comparaison pour le tri des pins par numero croissant
|
||
* du tableau des pins s_SortedComponentPinList par qsort()
|
||
*/
|
||
{
|
||
ObjetNetListStruct* Obj1, * Obj2;
|
||
int Num1, Num2;
|
||
char Line[5];
|
||
|
||
Obj1 = *Pin1; Obj2 = *Pin2;
|
||
Num1 = Obj1->m_PinNum; Num2 = Obj2->m_PinNum;
|
||
Line[4] = 0; memcpy( Line, &Num1, 4 ); Num1 = atoi( Line );
|
||
memcpy( Line, &Num2, 4 ); Num2 = atoi( Line );
|
||
return Num1 - Num2;
|
||
}
|
||
|
||
|
||
/*************************************************************************/
|
||
static void WriteGENERICListOfNets( FILE* f, ObjetNetListStruct* ObjNet )
|
||
/*************************************************************************/
|
||
|
||
/* Ecrit dans le fichier f la liste des nets ( classee par NetCodes ), et des
|
||
* elements qui y sont connectes
|
||
*/
|
||
{
|
||
int ii, jj;
|
||
int NetCode, LastNetCode = -1;
|
||
int SameNetcodeCount = 0;
|
||
EDA_SchComponentStruct* Cmp;
|
||
wxString NetName, CmpRef;
|
||
wxString NetcodeName;
|
||
char FirstItemInNet[1024];
|
||
|
||
for( ii = 0; ii < g_NbrObjNet; ii++ )
|
||
{
|
||
if( (NetCode = ObjNet[ii].GetNet()) != LastNetCode ) // New net found, write net id;
|
||
{
|
||
SameNetcodeCount = 0; // Items count for this net
|
||
NetName.Empty();
|
||
for( jj = 0; jj < g_NbrObjNet; jj++ ) // Find a label (if exists) for this net
|
||
{
|
||
if( ObjNet[jj].GetNet() != NetCode )
|
||
continue;
|
||
if( ( ObjNet[jj].m_Type != NET_GLOBLABEL)
|
||
&& ( ObjNet[jj].m_Type != NET_LABEL)
|
||
&& ( ObjNet[jj].m_Type != NET_PINLABEL) )
|
||
continue;
|
||
|
||
NetName = *g_TabObjNet[jj].m_Label; break;
|
||
}
|
||
|
||
NetcodeName.Printf( wxT( "Net %d " ), NetCode );
|
||
NetcodeName += wxT( "\"" );
|
||
if( !NetName.IsEmpty() )
|
||
{
|
||
NetcodeName += NetName;
|
||
if( g_TabObjNet[jj].m_Type != NET_PINLABEL ) // usual net name, add it the sheet number
|
||
NetcodeName << wxT( "_" ) << g_TabObjNet[jj].m_SheetNumber;
|
||
}
|
||
NetcodeName += wxT( "\"" );
|
||
LastNetCode = NetCode;
|
||
}
|
||
|
||
if( ObjNet[ii].m_Type != NET_PIN )
|
||
continue;
|
||
|
||
Cmp = (EDA_SchComponentStruct*) ObjNet[ii].m_Link;
|
||
CmpRef = Cmp->m_Field[REFERENCE].m_Text;
|
||
if( CmpRef.StartsWith( wxT( "#" ) ) )
|
||
continue; // Pseudo component (Like Power symbol)
|
||
|
||
// Print the pin list for this net, if 2 or more items are connected:
|
||
SameNetcodeCount++;
|
||
if( SameNetcodeCount == 1 ) /* first item for this net found,
|
||
* Print this connection, when a second item will be found */
|
||
{
|
||
sprintf( FirstItemInNet, " %s %.4s\n", CONV_TO_UTF8( CmpRef ),
|
||
(const char*) &ObjNet[ii].m_PinNum );
|
||
}
|
||
if( SameNetcodeCount == 2 ) // Second item for this net found, Print the Net name, and the first item
|
||
{
|
||
fprintf( f, "%s\n", CONV_TO_UTF8( NetcodeName ) );
|
||
fputs( FirstItemInNet, f );
|
||
}
|
||
|
||
if( SameNetcodeCount >= 2 )
|
||
fprintf( f, " %s %.4s\n", CONV_TO_UTF8( CmpRef ),
|
||
(const char*) &ObjNet[ii].m_PinNum );
|
||
}
|
||
}
|
||
|
||
|
||
/* Generation des netlistes au format CadStar */
|
||
wxString StartLine( wxT( "." ) );
|
||
|
||
/*********************************************************/
|
||
static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
|
||
/*********************************************************/
|
||
|
||
/* Routine de generation du fichier netliste ( Format CADSTAR )
|
||
* Entete:
|
||
* ..HEA
|
||
* ..TIM 2004 07 29 16 22 17
|
||
* ..APP "Cadstar RINF Output - Version 6.0.2.3"
|
||
* ..UNI INCH 1000.0 in
|
||
* ..TYP FULL
|
||
*
|
||
* liste des composants:
|
||
* ..ADD_COM X1 "CNT D41612 (48PTS MC CONTOUR)"
|
||
* ..ADD_COM U2 "74HCT245D" "74HCT245D"
|
||
*
|
||
* Connexions:
|
||
* ..ADD_TER RR2 6 "$42"
|
||
* ..TER U1 100
|
||
* CA 6
|
||
*
|
||
* ..ADD_TER U2 6 "$59"
|
||
* ..TER U7 39
|
||
* U6 17
|
||
* U1 122
|
||
*
|
||
* ..ADD_TER P2 1 "$9"
|
||
* ..TER T3 1
|
||
* U1 14
|
||
*/
|
||
{
|
||
wxString StartCmpDesc = StartLine + wxT( "ADD_COM" );
|
||
wxString msg;
|
||
wxString FootprintName;
|
||
char Line[1024];
|
||
BASE_SCREEN* CurrScreen;
|
||
EDA_BaseStruct* DrawList;
|
||
EDA_SchComponentStruct* Component;
|
||
wxString Title = g_Main_Title + wxT( " " ) + GetBuildVersion();
|
||
|
||
fprintf( f, "%sHEA\n", CONV_TO_UTF8( StartLine ) );
|
||
DateAndTime( Line );
|
||
fprintf( f, "%sTIM %s\n", CONV_TO_UTF8( StartLine ), Line );
|
||
fprintf( f, "%sAPP ", CONV_TO_UTF8( StartLine ) );
|
||
fprintf( f, "\"%s\"\n", CONV_TO_UTF8( Title ) );
|
||
fprintf( f, "\n" );
|
||
|
||
/* Create netlist module section */
|
||
ClearUsedFlags( frame ); /* Reset the flags FlagControlMulti in all schematic files*/
|
||
EDA_ScreenList ScreenList( NULL );
|
||
|
||
for( CurrScreen = ScreenList.GetFirst(); CurrScreen != NULL; CurrScreen = ScreenList.GetNext() )
|
||
{
|
||
for( DrawList = CurrScreen->EEDrawList; DrawList != NULL; DrawList = DrawList->Pnext )
|
||
{
|
||
DrawList = Component = FindNextComponentAndCreatPinList( DrawList );
|
||
if( Component == NULL )
|
||
break;
|
||
|
||
if( !Component->m_Field[FOOTPRINT].IsVoid() )
|
||
{
|
||
FootprintName = Component->m_Field[FOOTPRINT].m_Text;
|
||
FootprintName.Replace( wxT( " " ), wxT( "_" ) );
|
||
}
|
||
else
|
||
FootprintName = wxT( "$noname" );
|
||
|
||
msg = Component->m_Field[REFERENCE].m_Text;
|
||
msg.Replace( wxT( " " ), wxT( "_" ) );
|
||
fprintf( f, "%s ", CONV_TO_UTF8( StartCmpDesc ) );
|
||
fprintf( f, "%s", CONV_TO_UTF8( msg ) );
|
||
|
||
msg = Component->m_Field[VALUE].m_Text;
|
||
msg.Replace( wxT( " " ), wxT( "_" ) );
|
||
fprintf( f, " \"%s\"", CONV_TO_UTF8( msg ) );
|
||
fprintf( f, "\n" );
|
||
}
|
||
}
|
||
|
||
fprintf( f, "\n" );
|
||
|
||
MyFree( s_SortedComponentPinList );
|
||
s_SortedComponentPinList = NULL;
|
||
|
||
WriteListOfNetsCADSTAR( f, g_TabObjNet );
|
||
|
||
fprintf( f, "\n%sEND\n", CONV_TO_UTF8( StartLine ) );
|
||
}
|
||
|
||
|
||
/*************************************************************************/
|
||
static void WriteListOfNetsCADSTAR( FILE* f, ObjetNetListStruct* ObjNet )
|
||
/*************************************************************************/
|
||
|
||
/* Ecrit dans le fichier f la liste des nets ( classee par NetCodes ), et des
|
||
* pins qui y sont connectes
|
||
* format:
|
||
* .ADD_TER RR2 6 "$42"
|
||
* .TER U1 100
|
||
* CA 6
|
||
*/
|
||
{
|
||
wxString InitNetDesc = StartLine + wxT( "ADD_TER" );
|
||
wxString StartNetDesc = StartLine + wxT( "TER" );
|
||
wxString NetcodeName, InitNetDescLine;
|
||
int ii, jj, print_ter = 0;
|
||
int NetCode, LastNetCode = -1;
|
||
EDA_SchComponentStruct* Cmp;
|
||
wxString NetName;
|
||
|
||
for( ii = 0; ii < g_NbrObjNet; ii++ )
|
||
ObjNet[ii].m_Flag = 0;
|
||
|
||
for( ii = 0; ii < g_NbrObjNet; ii++ )
|
||
{
|
||
// Get the NetName of the current net :
|
||
if( (NetCode = ObjNet[ii].GetNet()) != LastNetCode )
|
||
{
|
||
NetName.Empty();
|
||
for( jj = 0; jj < g_NbrObjNet; jj++ )
|
||
{
|
||
if( ObjNet[jj].GetNet() != NetCode )
|
||
continue;
|
||
if( ( ObjNet[jj].m_Type != NET_GLOBLABEL)
|
||
&& ( ObjNet[jj].m_Type != NET_LABEL)
|
||
&& ( ObjNet[jj].m_Type != NET_PINLABEL) )
|
||
continue;
|
||
|
||
NetName = *ObjNet[jj].m_Label; break;
|
||
}
|
||
|
||
NetcodeName = wxT( "\"" );
|
||
if( !NetName.IsEmpty() )
|
||
{
|
||
NetcodeName += NetName;
|
||
if( g_TabObjNet[jj].m_Type != NET_PINLABEL )
|
||
NetcodeName << wxT( "_" ) << g_TabObjNet[jj].m_SheetNumber;
|
||
}
|
||
else // this net has no name: create a default name $<net number>
|
||
NetcodeName << wxT( "$" ) << NetCode;
|
||
NetcodeName += wxT( "\"" );
|
||
LastNetCode = NetCode;
|
||
print_ter = 0;
|
||
}
|
||
|
||
|
||
if( ObjNet[ii].m_Type != NET_PIN )
|
||
continue;
|
||
|
||
if( ObjNet[ii].m_Flag != 0 )
|
||
continue;
|
||
|
||
Cmp = (EDA_SchComponentStruct*) ObjNet[ii].m_Link;
|
||
|
||
if( Cmp->m_Field[REFERENCE].m_Text[0] == '#' )
|
||
continue; // Pseudo composant (symboles d'alims)
|
||
|
||
switch( print_ter )
|
||
{
|
||
case 0:
|
||
{
|
||
char buf[5];
|
||
wxString str_pinnum;
|
||
strncpy( buf, (char*) &ObjNet[ii].m_PinNum, 4 ); buf[4] = 0;
|
||
str_pinnum = CONV_FROM_UTF8( buf );
|
||
InitNetDescLine.Printf( wxT( "\n%s %s %.4s %s" ),
|
||
InitNetDesc.GetData(),
|
||
Cmp->m_Field[REFERENCE].m_Text.GetData(),
|
||
str_pinnum.GetData(), NetcodeName.GetData() );
|
||
}
|
||
print_ter++;
|
||
break;
|
||
|
||
case 1:
|
||
fprintf( f, "%s\n", CONV_TO_UTF8( InitNetDescLine ) );
|
||
fprintf( f, "%s %s %.4s\n",
|
||
CONV_TO_UTF8( StartNetDesc ),
|
||
CONV_TO_UTF8( Cmp->m_Field[REFERENCE].m_Text ),
|
||
(char*) &ObjNet[ii].m_PinNum );
|
||
print_ter++;
|
||
break;
|
||
|
||
default:
|
||
fprintf( f, " %s %.4s\n",
|
||
CONV_TO_UTF8( Cmp->m_Field[REFERENCE].m_Text ),
|
||
(char*) &ObjNet[ii].m_PinNum );
|
||
break;
|
||
}
|
||
|
||
ObjNet[ii].m_Flag = 1;
|
||
|
||
// Recherche des pins redondantes et mise a 1 de m_Flag,
|
||
// pour ne pas generer plusieurs fois la connexion
|
||
for( jj = ii + 1; jj < g_NbrObjNet; jj++ )
|
||
{
|
||
if( ObjNet[jj].GetNet() != NetCode )
|
||
break;
|
||
if( ObjNet[jj].m_Type != NET_PIN )
|
||
continue;
|
||
EDA_SchComponentStruct* tstcmp =
|
||
(EDA_SchComponentStruct*) ObjNet[jj].m_Link;
|
||
if( Cmp->m_Field[REFERENCE].m_Text != tstcmp->m_Field[REFERENCE].m_Text )
|
||
continue;
|
||
|
||
if( ObjNet[jj].m_PinNum == ObjNet[ii].m_PinNum )
|
||
ObjNet[jj].m_Flag = 1;
|
||
}
|
||
}
|
||
}
|