1 /****************************************************************************
2     Copyright (C) 1987-2015 by Jeffery P. Hansen
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, write to the Free Software Foundation, Inc.,
16     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 ****************************************************************************/
18 
19 #include "tkgate.h"
20 #include "switch.h"
21 #include "print.h"
22 
23 #define CENTER_JUST	(BetweenTopAndBottom|BetweenLeftAndRight)
24 
25 #define DIP_OUT 0
26 
27 extern int SimulatorActive;
28 
29 GCElement *Dip_Make(EditState **es,GModuleDef *env,int GType,
30 		    int x,int y,int r,const char *Name,int noWires,const char**,int);
31 
32 void Dip_Draw(GCElement *g,int md);
33 int Dip_EditProps(GCElement *g,int isLoadDialog);
34 void Dip_PSWrite(GPrint *P,GModLayout*,GCElement *g);
35 int Dip_SimHitFunc(EditState *ss,GCElement *g);
36 void Dip_SimInitFunc(EditState *es,GCElement *g,const char *path);
37 
38 static iconDimensions dip_iconDims[] = {
39   {0, 0, 75, 20, 37, 10},
40 };
41 static int dip_iconBoldOffset = 21;
42 
43 
44 GPadLoc dip_out_loc[] = {
45   {0,10,0,10,D_DOWN},
46   {38,0,38,0,D_RIGHT},
47   {0,-11,0,-11,D_UP},
48   {-38,0,-38,0,D_LEFT},
49 };
50 
51 static char *psDip[] = {
52   "%",
53   "% (v) x y r dip",
54   "%",
55   "/psdip {",
56   "  dup 4 1 roll",
57   "  startnorotgate",
58   "  3.5 0.5 translate",
59   "  -42 -10 moveto",
60   "  34 -10 lineto",
61   "  34 10 lineto",
62   "  -42 10 lineto",
63   "  closepath stroke",
64   "  8 rfont",
65   "  1 -1 scale",
66   "  -180 eq { 38 5 LJ } { -4 -12 CT } ifelse",
67   "  1 -1 scale",
68   "  5 rfont",
69   "  -38 3 moveto (ON) show",
70   "  -38 -6 moveto (OFF) show",
71   "  -24 7 25 {-5 ds} for",
72   "  grestore",
73   "} def",
74   0
75 };
76 
77 GGateInfo gate_dip_info = {
78   GC_DIP,
79   "DIP",
80   "dip",0x0u,
81   "psdip",psDip,
82   -1,-1,
83 
84   {{"d",	{"gm.io",0},	{"gm.io.dip",0,0,200},	"gat_make DIP"},
85    {0}},
86 
87   dip_iconDims,
88 
89   1,{{"Z",OUT,8,1,dip_out_loc}},
90   {{-42,0,RJ},{-35,23,LJ},{-35,23,LJ},{-35,23,LJ}},
91   {1,0,1,0,0,1},
92 
93   {0},
94 
95   Dip_Make,
96   Nop_WriteCellDef,
97   Generic_Init,
98   Generic_Delete,
99   Generic_GetExtents,
100   Generic_HitDistance,
101   Dip_Draw,
102   Generic_Move,
103   SwitchDip_Copy,
104   Err_AddInput,
105   Err_AddOutput,
106   Err_AddInOut,
107   Generic_Rotate,
108   Err_RemovePort,
109   Err_ChangePin,
110   Dip_SimInitFunc,
111   Dip_SimHitFunc,
112   Dip_PSWrite,
113   Dip_EditProps,
114   SwitchDip_VerSave,
115   SwitchDip_SetProp
116 };
117 
Dip_Make(EditState ** es,GModuleDef * env,int GType,int x,int y,int r,const char * Name,int noWires,const char ** options,int nOptions)118 GCElement *Dip_Make(EditState **es,GModuleDef *env,int GType,
119 		    int x,int y,int r,const char *Name,int noWires,const char **options,int nOptions)
120 {
121   GCElement *g;
122   const char *DefV;
123 
124   if (!(g = Generic_Make(es,env,GType,x,y,r,Name,noWires,options,nOptions)))
125     return NULL;
126 
127   DefV = seekOption("-value",options,nOptions);
128   if (!DefV || sscanf(DefV,"%d",&g->u.sw.dipval) != 1)
129     g->u.sw.dipval = 0;
130 
131   g->u.sw.perm_dipval = g->u.sw.dipval;
132 
133   g->u.sw.showNet = TkGate.circuit->showSwitchNets;
134 
135   return g;
136 }
137 
Dip_Draw(GCElement * g,int md)138 void Dip_Draw(GCElement *g,int md)
139 {
140   char s[STRMAX];
141   char compositeName[STRMAX];
142   int vox,voy;
143 
144   mk_gate(g->xpos,g->ypos,g->typeinfo,g->orient,g->selected);
145   gate_drawWires(g,md);
146 
147   SwitchDip_getCompositeName(g, compositeName);
148   if (*compositeName)
149     gate_drawgatename(g,compositeName);
150 
151   if (g->wires[DIP_OUT]) {
152     unsigned mask = nmask(g->wires[DIP_OUT]->net->n_nbits);
153     unsigned dipValue;
154 
155     if (tkgate_currentMode() == MM_SIMULATE)
156       dipValue = g->u.sw.dipval;
157     else
158       dipValue = g->u.sw.perm_dipval;
159 
160     sprintf(s,"%x",dipValue & mask);
161 
162     vox = (g->orient == 2) ?  43 : 0;
163     voy = (g->orient == 2) ?  5 : -15;
164 
165     if (g->selected)
166       XSetFont(TkGate.D,TkGate.instGC,TkGate.stextbXF[TkGate.circuit->zoom_factor]->fid);
167     else
168       XSetFont(TkGate.D,TkGate.instGC,TkGate.stextXF[TkGate.circuit->zoom_factor]->fid);
169     dce_DrawString(TkGate.instGC,g->xpos+vox,g->ypos+voy,
170 		   CENTER_JUST,s);
171   }
172 }
173 
Dip_PSWrite(GPrint * P,GModLayout * L,GCElement * g)174 void Dip_PSWrite(GPrint *P,GModLayout *L,GCElement *g)
175 {
176   Generic_PSLabels(P,g);
177 
178   fprintf(P->p_f,"(%x) %d %d %d %s\n",
179 	  g->u.sw.perm_dipval & nmask(g->wires[DIP_OUT]->net->n_nbits),
180 	  g->xpos,g->ypos,-g->orient*90,g->typeinfo->psprint);
181 }
182 
Dip_EditProps(GCElement * g,int isLoadDialog)183 int Dip_EditProps(GCElement *g,int isLoadDialog)
184 {
185   Tcl_Interp *tcl = TkGate.tcl;
186 
187   Generic_EditProps(g,isLoadDialog);
188   if (isLoadDialog) {
189     DoTcl("set ::edgat_dip %x",g->u.sw.perm_dipval);
190     DoTcl("set ::edgat_shownet %d",g->u.sw.showNet);
191   } else {
192     const char *p;
193 
194     ob_touch(g);
195 
196     if ((p = Tcl_GetVar(tcl,"edgat_dip",TCL_GLOBAL_ONLY)))
197       if (sscanf(p,"%x",&g->u.sw.perm_dipval) != 1)
198 	message(1,msgLookup("err.badhex"),p);	/* "Illegal hex value '%s' ignored." */
199     g->u.sw.dipval = g->u.sw.perm_dipval;
200 
201     if ((p = Tcl_GetVar(tcl,"edgat_shownet",TCL_GLOBAL_ONLY)))
202       sscanf(p,"%d",&g->u.sw.showNet);
203   }
204 
205   return 0;
206 }
207 
Dip_SimInitFunc(EditState * es,GCElement * g,const char * path)208 void Dip_SimInitFunc(EditState *es,GCElement *g,const char *path)
209 {
210   g->u.sw.dipval = g->u.sw.perm_dipval;
211 }
212 
Dip_SimHitFunc(EditState * es,GCElement * g)213 int Dip_SimHitFunc(EditState *es,GCElement *g)
214 {
215   GSimSwitch *ss = SHash_find(es->smod->switches,g->ename);
216 
217   DoTcl("Simulator::dipEntry %s %x %d %d",
218 	ss->gname,g->u.sw.dipval,
219 	ctow_x(g->xpos),ctow_y(g->ypos));
220 
221   return 1;
222 }
223 
init_dip()224 void init_dip()
225 {
226   Pixmap P;
227 
228   P = Pixmap_registerFromFile("dip","dip.b");
229   gateinfo_1iconInit(&gate_dip_info,P,dip_iconDims,dip_iconBoldOffset);
230   RegisterGate(&gate_dip_info);
231 }
232