divert(-1) libcct.m4 * Circuit_macros Version 5.2, copyright (c) 2002 J. D. Aplevich. * * The files of this distribution can be redistributed or modified, * * provided that this copyright notice is included, and provided that * * modifications are clearly marked to distinguish them from this * * distribution. There is no warranty whatsoever for these files. * Installation directory. You can set this to the null string if you use an environment variable to tell m4 where to search: ifdef(`HOMELIB_',, `define(`HOMELIB_',`/u/aplevich/lib/')') # `define(`HOMELIB_',`F:\home\lib\')') Default pic processor: gpic. To make dpic -p the default, change gpic.m4 to pstricks.m4. ifdef(`gpic_',, `ifdef(`pstricks_',, `ifdef(`mfpic_',, `ifdef(`postscript_',, `include(HOMELIB_`'gpic.m4)')')')')dnl divert(-1) ifdef(`right_',,`include(HOMELIB_`'libgen.m4)')dnl divert(-1) `============================================================================== THE ARGUMENTS of every circuit element are optional; if omitted, the current location, default length and direction are used. =============================================================================== With variations, 2-TERMINAL ELEMENTS are constructed as follows: # Draw the initial invisible line to length rp_len, and set the direction # cosines: eleminit_(`$1') # Element body height and width define(`m4v',...)define(`m4h',...) # Visible lines: { line to rvec_(rp_len/2-m4h/2,0) (element body lines) line to rvec_(rp_len/2-m4h/2,0) } # The invisible body block: {[box invis ht_ m4v wid_ m4h ] at rvec_(rp_len/2,0)} # The final invisible line: line to rvec_(rp_len,0) invis ============================================================================== DEBUGGING: A statement like the following inserted into a macro will print its arguments for debugging: print sprintf("`$0'(`$1',`$2',`$3')") ; ==============================================================================' `capacitor( linespec,C,R ) C = curved plate; R = reversed polarity' define(`capacitor',`eleminit_(`$1') ifelse(`$2',C,`m4Capacitor(`$3')',`m4capacitor') {[box invis ht_ m4v wid_ m4h ] at rvec_(rp_len/2,0)} line to rvec_(rp_len,0) invis') `straight plates: internal to capacitor' define(`m4capacitor',`define(`m4v',`dimen_/3')define(`m4h',`m4v*.3')dnl { line to rvec_(rp_len/2-m4h/2,0) {line from rvec_(0,-m4v/2) to rvec_(0,m4v/2)} move to rvec_(m4h,0) {line from rvec_(0,-m4v/2) to rvec_(0,m4v/2)} line to rvec_(rp_len/2-m4h/2,0) }') `curved plates: internal to capacitor' define(`m4Capacitor',`define(`m4v',`dimen_/4')dnl define(`m4h',`m4v*.4')define(`m4cr',`dimen_*.25')dnl { ifelse(`$1',R,`move to last line.end; rp_ang = rp_ang + pi_ ;')dnl line to rvec_(rp_len/2-m4h/2,0) {line from rvec_(0,-m4v/2) to rvec_(0,m4v/2)} {arc cw from rvec_(m4h,-m4v/2) to rvec_(m4h,m4v/2) \ with .c at rvec_(m4h+sqrt((m4cr)^2-(m4v/2)^2),0) } line from last arc.c+vec_(-m4cr,0) to rvec_(rp_len/2+m4h/2,0)dnl ifelse(`$1',R,` ; rp_ang = rp_ang - pi_') }') `resistor( linespec,cycles )' define(`resistor',`eleminit_(`$1') define(`m4n',`ifelse(`$2',,6,`eval(2*$2)')')dnl define(`m4v',`dimen_/12')define(`m4h',`dimen_/24')dnl {move to last line.c; line from last line.start to rvec_(prod_(m4n,-m4h),0) \ m4_resist(0)dnl then to rvec_(prod_(m4n,m4h), 0) then to last line.end } {[box invis ht_ 2*m4v wid_ prod_(m4n,2*m4h)] at 2nd last line.c } line from 2nd last line.start to 2nd last line.end invis ') define(`m4_resist',`ifelse(eval(`$1' ifelse(`$2',R,,`c')cw \ from rvec_(Rect_(dimen_/4,ifelse(`$2',R,,-)10))\ to rvec_(Rect_(dimen_/4,ifelse(`$2',R,-)75)) \ with .c at rvec_(rect_(-dimen_/4,ifelse(`$2',R,-)(75-10)/2*dtor_)) }') arrowht = m4t1 ; arrowwid = m4t2; [box invis ht_ dimen_/4+m4cs wid_ dimen_/4] \ with .c at rvec_(dimen_/8,ifelse(`$2',R,-)(m4v-(m4cs))/2)} {line from rvec_(rp_len/2+dimen_/6,0) to rvec_(rp_len,0)} line to rvec_(rp_len,0) invis') `Amplifier amp( linespec,size )' define(`amp',`eleminit_(`$1') define(`m4h',`ifelse(`$2',,`dimen_',`($2)')')dnl {line to rvec_(max(0,rp_len/2-m4h/2),0) line from rvec_(m4h,0) to rvec_(0,m4h/2) then to rvec_(0,-m4h/2) \ then to rvec_(m4h,0) then to rvec_(max(m4h,rp_len/2+m4h/2),0) } {[box invis ht_ m4h wid_ m4h] at rvec_(max(m4h,rp_len)/2,0)} line to rvec_(max(rp_len,m4h),0) invis') `integrator( linespec,size )' define(`integrator',`eleminit_(`$1') define(`m4h',`ifelse(`$2',,`dimen_',`($2)')')dnl {line from rvec_(m4h/4,m4h/2) to rvec_(0,m4h/2) then to rvec_(0,-m4h/2) \ then to rvec_(m4h/4,-m4h/2) } {line from rvec_(m4h*5/4,0) to rvec_(m4h/4,m4h/2) then to rvec_(m4h/4,-m4h/2) \ then to rvec_(m4h*5/4,0) then to rvec_(max(rp_len,m4h*5/4),0) } {[box invis ht_ m4h wid_ m4h*5/4] at rvec_(m4h*5/8,0)} line to rvec_(max(rp_len,m4h*5/4),0) invis') `opamp( linespec, -, +, size,P ) (as a []) arg 5: power connections V1,V2' define(`opamp',`[define(`m4h',`ifelse(`$4',,`dimen_',`($4)')')dnl rpoint_(ifelse(`$1',,`to rvec_(max(elen_-m4h/4,m4h),0)',`$1')) {line from rvec_(m4h,0) to rvec_(0,m4h/2) then to rvec_(0,-m4h/2) \ then to rvec_(m4h,0) then to rvec_(max(m4h,rp_len),0) Out: Here } In1: rvec_(0,m4h/4) { ifelse(`$2',,"sp_{\small$-$}sp_",`$2') at In1 ljust_ } In2: rvec_(0,-m4h/4) { ifelse(`$3',,"sp_{\small$+$}sp_",`$3') at In2 ljust_ } ifelse(`$5',P, `{line from rvec_(m4h/2,m4h/4) to rvec_(m4h/2,m4h/4+m4h/8); V1: Here} {line from rvec_(m4h/2,-m4h/4) to rvec_(m4h/2,-(m4h/4+m4h/8)); V2: Here}') ] ') `diode( linespec, B|S|T|Z|LE|LER , R ) Arg 3: reversed polarity' define(`diode',`eleminit_(`$1')dnl ifelse(`$3',R,`move to last line.end; eleminit_(to last line.start)') ifelse(`$2',,`m4plain_d', index(`$2',B),0, `m4bidirect_di', `$2',S, `m4plain_d(S)', `$2',T, `m4plain_d(T)', `$2',Z, `m4plain_d(Z)', substr(`$2',0,2),LE, `m4plain_d ifelse(`$2',LER,`{em_arrows(,D) at rvec_(rp_len/2-m4h,-m4v*2)}', `{em_arrows at rvec_(rp_len/2-m4h,m4v*2)}') ') { [box invis ht_ m4v wid_ m4h] at rvec_(rp_len/2,0) } line invis ifelse(`$3',R,`from rvec_(rp_len,0) to Here', `to rvec_(rp_len,0)') ') define(`m4plain_d',`define(`m4v',`dimen_/5')define(`m4h',`sqrt(3)*m4v/2')dnl { m4_arrow(to rvec_(rp_len/2+m4h/2,0),m4h,m4v) { line from ifelse( `$1',S,`rvec_(-m4v/4,-m4v/3) to rvec_(-m4v/4,-m4v*2/3) \ then to rvec_(0,-m4v*2/3) then to rvec_(0,m4v*2/3) \ then to rvec_(m4v/4,m4v*2/3) then to rvec_(m4v/4,m4v/3)', `$1',T,`rvec_(-m4v/4,-m4v/2) to rvec_(0,-m4v/2) then to rvec_(0,m4v/2) \ then to rvec_(-m4v/4,m4v/2)', `$1',Z,`rvec_(-m4v/4,-m4v/2) to rvec_(0,-m4v/2) then to rvec_(0,m4v/2) \ then to rvec_( m4v/4,m4v/2)', `rvec_(0,-m4v/2) to rvec_(0,m4v/2)') } line to rvec_(rp_len/2-m4h/2,0) } ') define(`m4bidirect_di',`define(`m4v',`dimen_/5')define(`m4h',`sqrt(3)*m4v')dnl { m4_arrow(to rvec_(rp_len/2,0),m4h/2,m4v) {m4_arrow(from rvec_(rp_len/2,0) to Here,m4h/2,m4v)} { line from rvec_(-m4v/4,-m4v/2) to rvec_(0,-m4v/2) then to rvec_(0,m4v/2) \ then to rvec_(m4v/4,m4v/2) } } ') define(`em_arrows',`[dnl `em_arrows(L | R, U | D)' arrow to rvec_(ifelse(`$1',R,,-)dimen_/3,ifelse(`$2',D,-,)dimen_/3) \ wid dimen_/9 ht dimen_/6 move to rvec_(ifelse(`$1',R,-,)dimen_/8,ifelse(`$2',D,-,)dimen_/8) arrow <- to rvec_(ifelse(`$1',R,-,)dimen_/3,ifelse(`$2',D,,-)dimen_/3) \ wid dimen_/9 ht dimen_/6]') define(`bi_tr',`dnl `Bipolar transistor bi_tr(linespec, L|R, P, E)' [ define(`m4_U',dimen_/10) ifelse(`$1',,,`eleminit_($1)') E: Here ifelse(`$1',,,`line to rvec_( rp_len/2-3*m4_U,0)') line to rvec_(m4_U*1.8,ifelse(`$2',R,-)4*m4_U) {arrow from last line.ifelse(`$3',P,`start to 3',`end to 1')/4 \ between last line.start and Here wid m4_U*10/9 ht m4_U*10/6} Bulk: line from rvec_(-m4_U*.8,0) to rvec_(m4_U*3.2,0) line from rvec_(-m4_U*.8,0) to rvec_(m4_U,ifelse(`$2',R,,-)4*m4_U) ifelse(`$1',,,`line to rvec_(rp_len/2-3*m4_U,0)') C: Here B: Bulk.c+vec_(0,ifelse(`$2',R,-)2.5*m4_U) line from B to Bulk.c ifelse(`$4',E,dnl `circle rad 4*m4_U with .c at Bulk.c+vec_(0,ifelse(`$2',R,,-)1.5*m4_U)') manhattan]') `Unijunction transistor ujt(linespec, R,P,E ) Bulk and terminals B1, B2, E defined arg 2: drawn to the right of curr direction arg 3: P-channel, default N arg 4: envelope' define(`ujt', `[ define(`m4_U',dimen_/10) ifelse(`$1',,,`eleminit_($1)') B1: Here ifelse(`$1',,,`line to rvec_(rp_len/2-m4_U*2,0)') line to rvec_(0,ifelse(`$2',R,-)3.5*m4_U) Bulk: line from rvec_(-m4_U*.5,0) to rvec_(m4_U*4.5,0) line from Bulk.end+vec_(-m4_U/2,0) \ to Bulk.end+vec_(-m4_U/2,ifelse(`$2',R,,-)3.5*m4_U) \ ifelse(`$1',,,`then to Bulk.c+vec_(rp_len/2,ifelse(`$2',R,,-)3.5*m4_U)') B2: Here E: Bulk.c+vec_(2*m4_U,ifelse(`$2',R,-)3.5*m4_U) line from E to Bulk.center {arrow from last line.ifelse(`$3',P,`end to 1',`start to 7')/8 \ between last line.start and last line.end wid m4_U*10/9 ht m4_U*10/6} ifelse(`$4',E,dnl `circle rad 4*m4_U with .c at Bulk.c') manhattan] ') `Triac scr(linespec, R,G,E ) arg 2: gate to the right of curr direction arg 3: full-size gate terminal arg 4: envelope' define(`scr',`define(`m4_U',`dimen_/10')dnl [define(`m4v',`dimen_/5*2')define(`m4h',`sqrt(3)*dimen_/5/2')dnl T1: Here rpoint_(ifelse(`$1',,`to rvec_(8*m4_U,0)',`$1')) line to rvec_(rp_len/2-m4h/2,0) define(`m4n',`ifelse(`$2',,,-)m4v/4')dnl { m4_arrow(from rvec_(0,m4n) to rvec_(m4h,m4n),m4h,m4v/2) line from rvec_(0,m4n) to rvec_(0,-3*(m4n)) } { m4_arrow(from rvec_(m4h,-(m4n)) to rvec_(0,-(m4n)),m4h,m4v/2) line from rvec_(0,-(m4n)) to rvec_(0,3*(m4n)) } { line to ifelse(`$3',G,,3/)2 between Here and rvec_(m4h,m4n) ifelse(`$3',,,`\ then to rvec_(m4h*2,ifelse(`$2',,,-)sqrt((4*m4_U)^2-(m4h*3/2)^2))') G: Here } ifelse(`$4',,,`{ circle rad 4*m4_U with .c at rvec_(m4h/2,0)}') line from rvec_(m4h,0) to rvec_(rp_len/2+m4h/2,0) T2: Here ]') `JFET j_fet(linespec, R, P, E ) Bulk and terminals S, D, G defined arg 2: drawn to the right of curr direction arg 3: P-channel, default N arg 4: envelope' define(`j_fet', `[ define(`m4_U',dimen_/10) ifelse(`$1',,,`eleminit_($1)') S: Here ifelse(`$1',,,`line to rvec_(rp_len/2-m4_U*2,0)') line to rvec_(0,ifelse(`$2',R,-)3.5*m4_U) Bulk: line from rvec_(-m4_U*.5,0) to rvec_(m4_U*4.5,0) line from Bulk.end+vec_(-m4_U/2,0) \ to Bulk.end+vec_(-m4_U/2,ifelse(`$2',R,,-)3.5*m4_U) \ ifelse(`$1',,,`then to Bulk.c+vec_(rp_len/2,ifelse(`$2',R,,-)3.5*m4_U)') D: Here G: Bulk.start+vec_(m4_U/2,ifelse(`$2',R,-)3.5*m4_U) line from G to Bulk.start+vec_(m4_U/2,0) {arrow from last line.ifelse(`$3',P,`end to 1',`start to 7')/8 \ between last line.start and last line.end wid m4_U*10/9 ht m4_U*10/6} ifelse(`$4',E,dnl `circle rad 4*m4_U with .c at Bulk.c') manhattan] ') `Enhancement-mode FET e_fet(linespec,L|R,P,S,E) arg 3: p-channel, default n-channel arg 4: simplified diagram arg 5: envelope' define(`e_fet',`ifelse(`$4',S,`smosfet',`mosfet')(`$1',`$2',`$3',,`$5')') `Depletion-mode FET d_fet(linespec,L|R,P,S,E) arg 3: p-channel, default n-channel arg 4: simplified diagram arg 5: envelope' define(`d_fet',`ifelse(`$4',S,`smosfet',`mosfet')(`$1',`$2',`$3',D,`$5')') `mosfet(linespec,L|R,P,[D][B],E) arg 3: p-channel, default n-channel arg 4: D=depletion mode B=disconnected substrate arg 5: envelope' define(`mosfet',`[ define(`m4_U',dimen_/10) ifelse(`$1',,,`eleminit_($1)') S: Here ifelse(`$1',,,`line to rvec_(rp_len/2-m4_U*2,0)') {line to rvec_(m4_U*2,0) ifelse(index(`$4',B),-1,,`invis; B: Here') line to rvec_(0,ifelse(`$2',R,-)m4_U*3.5) arrow from last line.ifelse(`$3',P,end to 1,start to 4)/5 \ between last line.start and last line.end wid m4_U*10/9 ht m4_U*10/6} line to rvec_(0,ifelse(`$2',R,-)3.5*m4_U); move to rvec_(-m4_U/2,0) ifelse(index(`$4',D),-1, `{Channel: line invis to rvec_(m4_U*5,0)} line to rvec_(m4_U*3/2,0) move to rvec_(m4_U/2,0); line to rvec_(m4_U,0); move to rvec_(m4_U/2,0) line to rvec_(m4_U*3/2,0)', `Channel: line to rvec_(m4_U*5,0)' ) line from Channel.end+vec_(-m4_U/2,0) to \ Channel.end+vec_(-m4_U/2,ifelse(`$2',R,,-)3.5*m4_U) ifelse(`$1',,,`line to rvec_(rp_len/2-2*m4_U,0)') D: Here G: Channel.start+vec_(m4_U/2,ifelse(`$2',R,-)3.5*m4_U) line from G to Channel.start+vec_(m4_U/2,ifelse(`$2',R,-)m4_U) \ then to Channel.start+vec_(m4_U*9/2,ifelse(`$2',R,-)m4_U) ifelse(`$5',E,`circle rad 4*m4_U with .c at Channel.c') manhattan] ') `Simplified diagram smosfet(linespec,L|R,P,D,E) arg 3: p-channel, default n-channel arg 4: depletion mode, default enhancement' arg 5: envelope' define(`smosfet',`[ define(`m4_U',dimen_/10) ifelse(`$1',,,`eleminit_($1)') S: Here ifelse(`$1',,,`line to rvec_(rp_len/2-m4_U*2,0)') line to rvec_(0,ifelse(`$2',R,-)3.5*m4_U) {arrow from last line.ifelse(`$3',P,start to 4,end to 1)/5 \ between last line.start and last line.end wid m4_U*10/9 ht m4_U*10/6} ifelse(`$4',D,`{move to rvec_(0,ifelse(`$2',R,,-)linethick*3/2pt__) line thick 2*linethick to rvec_(m4_U*4,0)}') Channel: line from rvec_(-m4_U/2,0) to rvec_(m4_U*9/2,0) line from Channel.end+vec_(-m4_U/2,0) to \ Channel.end+vec_(-m4_U/2,ifelse(`$2',R,,-)3.5*m4_U) ifelse(`$1',,,`line to rvec_(rp_len/2-2*m4_U,0)') D: Here G: Channel.c+vec_(0,ifelse(`$2',R,-)ifelse(`$5',E,4,3.5)*m4_U) line from G to Channel.c+vec_(0,ifelse(`$2',R,-)m4_U) line from rvec_(-m4_U*3/2,0) to rvec_(m4_U*3/2,0) ifelse(`$5',E,`circle rad 4*m4_U with .c at Channel.c') manhattan] ') `Element labels to the left, right, centre of the current direction. Labels are spaced and treated as math, but copied literally if double quoted' define(`rlabel',`m4label(`$1',`$2',`$3',.s_,below_)') define(`llabel',`m4label(`$1',`$2',`$3',.n_,above_)') define(`clabel',`m4label(`$1',`$2',`$3',,)') labels at centre and both ends of an element `dimen_' long define(`m4label',`dnl ifelse(`$1',,, `{ifelse(index(`$1',"),0,`$1',"sp_$`$1'$sp_") at last [].w_ $5 rjust_};')dnl ifelse(`$2',,, `{ifelse(index(`$2',"),0,`$2',"sp_$`$2'$sp_") at last []$4 $5};')dnl ifelse(`$3',,, `{ifelse(index(`$3',"),0,`$3',"sp_$`$3'$sp_") at last [].e_ $5 ljust_};')dnl ') `Oblique element label dlabel(long,lateral,label,label,label)' define(`dlabel',`dnl ifelse(`$3',,, `{ifelse(index(`$3',"),0,`$3',"$`$3'$") at last [].c+vec_(-(`$1'),`$2')};')dnl ifelse(`$4',,, `{ifelse(index(`$4',"),0,`$4',"$`$4'$") at last [].c+vec_(0,`$2')};')dnl ifelse(`$5',,, `{ifelse(index(`$5',"),0,`$5',"$`$5'$") at last [].c+vec_(`$1',`$2')};') ') `eleminit_( linespec ) compute element direction and length' define(`eleminit_',`rpoint_(ifelse(`$1',,`to rvec_(elen_,0)',`$1'))') `par_( element, element, separation ) Parallel combination of two branches that have the same direction and length. The branch arguments must be quoted, e.g. par_(`resistor',`capacitor',dimen_)' define(`par_',`[Start: Here; r = ifelse(`$3',,`dimen_',`$3') { move to Start + vec_(0,r/2); $1 } line from Start + vec_(0,r/2) to Start + vec_(0,-r/2) ; $2 End: line to rvec_(0,r) ] with .Start at Here move to last [].End') `gpar_( element, element, separation ) Parallel combination of two branches that have the same direction, e.g.: down_; gpar_( resistor;llabel(,R_1);resistor;llabel(,R_2), capacitor;rlabel(,C)) This macro trades simplicity for generality and robustness to gpic' define(`gpar_', `[ M4_B1: Here; `$1'; M4_E1: Here M4_C: 0.5 between M4_B1 and M4_E1; eleminit_(from M4_B1 to M4_E1) E2:[ M4_B: Here; `$2'; M4_E: Here ] \ with .c at M4_C + (rect_(ifelse(`$3',,`dimen_',`$3'),rp_ang-pi_/2)) M4_B2: E2.M4_B; M4_E2: E2.M4_E s = distance(M4_B2,M4_E2) if rp_len*s == 0 then { r = 1 } else { r = (1+max(rp_len/s, s/rp_len))/2 } if rp_len < s then { Tmp:M4_B2; M4_B2:M4_B1; M4_B1:Tmp Tmp:M4_E2; M4_E2:M4_E1; M4_E1:Tmp } line from M4_B2 to r between M4_E2 and M4_B2 Start: 0.5 between Here and M4_B1; line to M4_B1 line from M4_E2 to r between M4_B2 and M4_E2 End: 0.5 between Here and M4_E1; line to M4_E1 ] with .Start at Here move to last [].End ') `reversed(macro name in quotes, macro args) reverse polarity of two-terminal element' define(`reversed',`eleminit_(`$2') $1(from last line.end to last line.start,shift(shift($@))) rp_ht = -rp_ht; rp_wid = -rp_wid; rp_ang = rp_ang - pi_ line invis to last line.start') `Line hopping over named lines, diverting left or right: crossover(linespec,L|R,line_name,line_name,...)' define(`hoprad_',`dimen_/12') define(`crossover',`eleminit_(`$1')dnl M4_Tmp: last line.end m4_xover_(shift($@))dnl line to M4_Tmp ') `internal to crossover:' define(`m4_xover_',`ifelse(`$2',,,`line to \ intersect_(last line.start,M4_Tmp,`$2'.start,`$2'.end) chop 0 chop hoprad_ arc ifelse(`$1',R,c)cw to rvec_(2*hoprad_,0) with .c at rvec_(hoprad_,0) m4_xover_(`$1',shift(shift($@)))')') `relay(poles,O|C,R), Number of poles (max 10), double-throw (default) or normally open or closed, drawn left (default) or right' define(`relay',`[define(`m4n',`ifelse(`$3',R,-,0+)') V1: Here line to rvec_(dimen_/5,0) line to rvec_(0,dimen_/4) then to rvec_(dimen_/5,dimen_/4) \ then to rvec_(dimen_/5,-dimen_/4) then to rvec_(0,-dimen_/4) then to Here line from rvec_(dimen_/5,0) to rvec_(2*dimen_/5,0) V2: Here move to V2+vec_(dimen_/12,m4n (dimen_/4+dimen_/5)) m4_contacts(1,ifelse(`$1',,1,`$1'),`$2',`$3') ifelse(`$1',,,`ifelse(eval(`$1'>1),1,`line dashed \ from P1+vec_(dimen_*.261,-(m4n dimen_/10)) \ to P`$1'+vec_(dimen_*.261,m4n dimen_/10)')') ] ') define(`m4_contacts',`contact(`$3',`$4') with .O at Here define(`m4v',`ifelse(`$1',,1,`$1')')dnl P`$1': last [].P ifelse(`$3',O,,C`$1': last [].C) ifelse(`$3',C,,O`$1': last [].O) ifelse(m4v,`$2',,`move to last[].C+(0,m4n dimen_/5) ifelse(eval(m4v<11),1,`m4_contacts(incr(m4v),`$2',`$3',`$4')')')') `contact(O|C,R) Relay contact switch, double-throw (default) or normally open or closed, to left or right' define(`contact',`[define(`m4n',`ifelse(`$2',R,-,0+)')dnl P:dot; line to rvec_(dimen_/2,0) T: P + vec_(dimen_/2-dimen_/18,0) O: P+vec_(dimen_*(1/2-1/18+1/5),-(m4n dotrad_)) C: P+vec_(dimen_*(1/2-1/18+1/5),m4n dotrad_) ifelse(`$1',O,,`arrow <- ht dimen_/6 wid dimen_/6 \ from T to T+vec_(0,m4n dimen_/4) then to T+vec_(dimen_/5,m4n dimen_/4) C: Here') ifelse(`$1',C,,`arrow <- ht dimen_/6 wid dimen_/6 \ from T+vec_(0,-(m4n dimen_/8)) \ to T+vec_(0,-(m4n (dimen_/4+dimen_/8))) \ then to T+vec_(dimen_/5,-(m4n (dimen_/4+dimen_/8))) O: Here') ] ') `nport(box specs,nw,ne,nn,ns,space ratio,pin lgth) Default is a standard-box twoport. Args 2 to 5 are the number of ports to be drawn on w, n, e, s sides. The port pins are named by side, number and by a or b pin, e.g. W1a, W1b, W2a, ... . Arg 6 specifies the ratio of port width to interport space, and arg 7 is the pin len' define(`nport',`[Box: box `$1' r = ifelse(`$6',,2.0,`$6') plg = ifelse(`$7',,`dimen_/4',`$7') # `West side' define(`m4_n',`ifelse(`$2',,1,`($2)')') d = Box.ht/(m4_n*(r+1)+1) move to Box.nw+(0,-d); down_ portpins(1,+1,m4_n,-plg,d*r,d,W) # `North side' ifelse(`$3',,,`define(`m4_n',`($3)') d = Box.wid/(m4_n*(r+1)+1) move to Box.nw+(d,0); right_ portpins(1,+1,m4_n,plg,d*r,d,N)') # `East side' define(`m4_n',`ifelse(`$4',,1,`($4)')') d = Box.ht/(m4_n*(r+1)+1) move to Box.ne+(0,-d); down_ portpins(1,+1,m4_n,plg,d*r,d,E) # `South side' ifelse(`$5',,,`define(`m4_n',`($5)') d = Box.wid/(m4_n*(r+1)+1) move to Box.sw+(d,0); right_ portpins(1,+1,m4_n,-plg,d*r,d,S)') ]') `portpins(index,signed incr,final,height,wd,sep,label) Recursive macro to draw a port sequence' define(`portpins',`ifelse(eval($1),eval($3$2),, `{line to rvec_(0,`$4'); `$7$1'a: dot } move to rvec_(`$5',0) {line to rvec_(0,`$4'); `$7$1'b: dot } move to rvec_(`$6',0) portpins(eval($1$2),shift($@)) ')') `Signal-flow graph macros. There are definitions for a labeled node, a directed labeled chopped straight line, and a directed labeled chopped arc. All are contained in [] blocks.' `Initialization macro sfg_init(line len, node rad, arrowhd len, arrowhd wid)' define(`sfg_init',` sfg_wid = ifelse(`$1',,`linewid/.75*(2.5+.25)/4',`$1') # default line len sfg_rad = ifelse(`$2',,0.25/4/2,`$2') # node radius sfg_aht = ifelse(`$3',,0.25/4,`$3') # arrow height (arrowhead length) sfg_awid = ifelse(`$4',,`sfg_aht',`$4')# arrowhead width ') `sfgline(linespec,text, sfgabove|sfgbelow|ljust|rjust) Draw a straight line with linespec, chopped by node radius, with optional label' define(`sfgline',`rpoint_(ifelse(`$1',,`to rvec_(sfg_wid,0)',`$1')) [ line to rvec_(rp_len,0) chop sfg_rad Start: last line.start End: Here { arrow ht sfg_aht wid sfg_awid \ from Start to (0.5+sfg_aht/2/lin_leng(last line)) between Start and End ifelse(`$2',,,`"$`$2'$" ifelse(`$3',,`sfgabove',`$3')') } ] with .Start at rvec_(sfg_rad,0) move to last [].End ') `Like above_ or below_ but adding extra space to put text above or below arrowheads or nodes' define(`sfgabove',`at rvec_(0,sfg_awid/2) above_') define(`sfgbelow',`at rvec_(0,-sfg_awid/2) below_') `sfgnode(at pos,text,above_) Node: a white circle, possibly labelled' define(`sfgnode',`[circle rad sfg_rad thickness 0.5] ifelse(`$1',,,`with .c $1') move to last [].c ifelse(`$2',,,`{"$`$2'$" ifelse(`$3',,`sfgabove',`$3')}') ') `sfgarc(linespec,label,above_,cw|ccw,sfact) An arc between nodes at the endpoints of the linespec. The resulting positions Start, End, C (arc center) and M (arc midpoint) are defined. The fifth argument scales the arc height above its chord.' define(`sfgarc',`dnl rpoint_(ifelse(`$1',,`to rvec_(sfg_wid,0)',`$1')) [ Start: Here End: Start + vec_(rp_len,0) y = (rp_len/sqrt(2)-rp_len/2)ifelse(`$5',,,`*($5)') ll = (y^2+rp_len^2/4)/y/2 C: 0.5 between Start and End; C: C + vec_(0,ifelse(`$4',ccw,,-)(ll-y)) h = sfg_rad^2/ll/2 v = sqrt(sfg_rad^2-h^2) cth = ifelse(`$4',ccw,-)rp_len/2/ll sth = (ll-y)/ll M: C + vec_( 0,ifelse(`$4',ccw,-)ll) arc -> ifelse(`$4',ccw,ccw,cw) from Start+vec_(sth*v+cth*h,cth*v-sth*h) \ to C + vec_( sfg_aht/2,ifelse(`$4',ccw,-)sqrt(ll^2-sfg_aht^2/4)) \ ht sfg_aht wid sfg_awid with .c at C ifelse(`$2',,,`{"$`$2'$" ifelse(`$3',,`sfgabove',`$3')}') arc ifelse(`$4',ccw,ccw,cw) to End+vec_(-sth*v-cth*h,cth*v-sth*h) with .c at C ] with .Start at last line.start move to last line.end ') Size parameters: they must all be terms (products), i.e. a sum would have to be parenthesized define(`dimen_',`linewid') Source element default radius define(`sourcerad_',`0.25*dimen_') Controlled Source width/2 define(`csdim_',`dimen_*0.3') Element length: define(`elen_',`dimen_*3/2') Delay elements: define(`delay_rad_',`0.35*dimen_') Redefine dot size for circuits define(`dotrad_',`0.04*dimen_') right_ Initialize global variables: define(`cct_init',`dnl `#' `$0': ifdef(`gpic_',`Gpic', `ifdef(`pstricks_',`PSTricks', `ifdef(`mfpic_',`mfpic',`default')')') m4 macro settings detected. gen_init dnl dnl Customizations can be put here ') divert(0)dnl psset_(arrowsize=1.2pt 4`,'arrowlength=1.64`,'arrowinset=0)dnl