-- File: [Thyme]<Thyme>System>CSIM01>spFunctions.mesa
-- Last editted:
-- by Barth, July 11, 1983  1:53 PM
-- Wilhelm April 6, 1982  12:17 PM, reformated by Barth and stored under
--   [Cherry]<Barth>Thyme>1.97> . 
DIRECTORY AltoDefs, Real, spModelDefs;
spFunctions:  PROGRAM
  IMPORTS Real, spModelDefs =
  BEGIN

    functionError:  SIGNAL[s:  STRING] = CODE;

    SimpleFET:  spModelDefs.function =
      BEGIN
        Vgate:    CARDINAL = 0;
        Vsource:  CARDINAL = 1;
        Vdrain:   CARDINAL = 2;

        Vt:    CARDINAL = 0;
        Gain:  CARDINAL = 1;

        Vds, Vgst:  REAL;

        Vds ← args[Vdrain] - args[Vsource];
        IF Vds >= 0 THEN
          BEGIN
            Vgst ← args[Vgate] - args[Vsource] - parms[Vt];
            IF Vgst > 0 THEN
              BEGIN
                IF Vds > Vgst THEN v ← 0.5*parms[Gain]*Vgst*Vgst
                ELSE v ← parms[Gain]*(Vgst - 0.5*Vds)*Vds
              END
            ELSE v ← 0.01*parms[Gain]
          END
        ELSE
          BEGIN
            Vds ← -Vds;
            Vgst ← args[Vgate] - args[Vdrain] - parms[Vt];
            IF Vgst > 0 THEN
              BEGIN
                IF Vds > Vgst THEN v ← -0.5*parms[Gain]*Vgst*Vgst
                ELSE v ← -parms[Gain]*(Vgst - 0.5*Vds)*Vds
              END
            ELSE v ← -0.01*parms[Gain]
          END
      END;

    PulseGen: spModelDefs.function =
      BEGIN
        onLevel:   CARDINAL = 0;
        offLevel:  CARDINAL = 1;
        period:    CARDINAL = 2;
        width:     CARDINAL = 3;
        tRise:     CARDINAL = 4;
        tFall:     CARDINAL = 5;
        tDelay:    CARDINAL = 6;

        time:  REAL ← t - parms[tDelay];
        nperiods:   INTEGER;
        tRel:  REAL;

        nperiods ← Real.FixI[time/parms[period]
          ! Real.RealException => spModelDefs.Failure[750]];
        tRel ← IF time > 0.0 THEN time - nperiods*parms[period]
               ELSE time + (1 - nperiods)*parms[period];
        v ← IF tRel >= parms[width] THEN parms[offLevel]
            ELSE
              IF tRel < parms[tRise] THEN
                 parms[offLevel] + (parms[onLevel] -
                                    parms[offLevel])*tRel/parms[tRise]
              ELSE
                IF tRel <= parms[width] - parms[tFall] THEN
                   parms[onLevel]
                ELSE
                   parms[offLevel] + (parms[width] - tRel)*
                   (parms[onLevel] - parms[offLevel])/parms[tFall]
      END;

    OneShotGen: spModelDefs.function =
      BEGIN
        onLevel:   CARDINAL = 0;
        offLevel:  CARDINAL = 1;
        width:     CARDINAL = 2;
        tRise:     CARDINAL = 3;
        tFall:     CARDINAL = 4;
        tDelay:    CARDINAL = 5;

        tRel:  REAL ← t - parms[tDelay];

        v ← IF tRel < 0.0 OR tRel >= parms[width] THEN parms[offLevel]
            ELSE
              IF tRel < parms[tRise] THEN
                 parms[offLevel] + (parms[onLevel] -
                                    parms[offLevel])*tRel/parms[tRise]
              ELSE
                IF tRel <= parms[width] - parms[tFall] THEN
                   parms[onLevel]
                ELSE
                   parms[offLevel] + (parms[width] - tRel)*
                   (parms[onLevel] - parms[offLevel])/parms[tFall]
      END;

    StepGen:  spModelDefs.function =
      BEGIN
        onLevel:   CARDINAL = 0;
        offLevel:  CARDINAL = 1;
        tRise:     CARDINAL = 2;
        tDelay:    CARDINAL = 3;

        v ← IF t <= parms[tDelay] THEN parms[offLevel]
            ELSE
              IF t >= parms[tDelay] + parms[tRise] THEN parms[onLevel]
              ELSE parms[offLevel] + (t - parms[tDelay])*
                   (parms[onLevel] - parms[offLevel])/parms[tRise]
      END;

    spModelDefs.EnterFunctions["OneShotGen", OneShotGen, 0, 6];
    spModelDefs.EnterFunctions["PulseGen",   PulseGen,   0, 7];
    spModelDefs.EnterFunctions["SimpleFET",  SimpleFET,  3, 2];
    spModelDefs.EnterFunctions["StepGen",    StepGen,    0, 4]
  END.