package nxm.sys.prim;

import nxm.sys.inc.*;
import nxm.sys.lib.*;
import nxm.sys.libm.Waveform;

/**
  Creates signal waveforms of various shapes.

  @author Jeff Schoen
  @version $Id: waveform.java,v 1.15 2002/09/09 21:02:39 schoenj Exp $
  @see <a href="../exp/waveform.exp">Explain</a>
  @see <a href="waveform.java">Source</a>

*/
public final class waveform extends Primitive {

  private Data data;
  private DataFile hcb;
  private double amp, freq, poff, phase, chirp, dt;
  private int shape,throttle,mode;

  public  final static String shapeList = 
    "Sinusoid,Square,Triangle,Sawtooth,Pulse,Constant,Zero,White,Ramp";
  private final static int 
    SIN=1,SQU=2,TRI=3,SAW=4,PUL=5,CON=6,ZER=7,WHI=8,RAM=9;

  public  final static String throttleList = "RealTime,Full,Block";
  private final static int REALTIME=1,FULL=2,BLOCK=3;

  public int open() {

    // Get parameters
    shape = MA.getChoice("SHAPE",shapeList,0); 
    freq  = MA.getD("FREQ");
    amp   = MA.getD("AMP");
    poff  = MA.getD("PHASE");
    chirp = MA.getD("CHIRP",0.0);

    // Open output file
    hcb = MA.getDataFile("OUT","1000","SF",0); 
    hcb.setFormat (MA.getFormat("FORM","S#,C#"));
    hcb.setXStart (MA.getD("START"));
    hcb.setXDelta (MA.getD("DELTA"));
    hcb.setXUnits (Units.TIME);
    hcb.setSize   (MA.getD("ELEM"));
    hcb.open();

    // Setup processing
    throttle = MA.getChoice("/RT",throttleList,FULL);
    mode = hcb.spa;
    xfer = MA.getL("/TL",4096);
    data = hcb.getDataBuffer(xfer,FLOAT);
    dt = hcb.getXDelta();
    todo(hcb.size);

    return (NORMAL);
  }
	
  public int process() {
    
    double p, dp, ddp;
    float[] fbuf;

    if (throttle==BLOCK) return (NOOP);
    int ndo = todo();
    if (ndo==0) return (FINISH);

    data.setSize(ndo);			// size data object for this pass

    fbuf = data.castF(false);		// get array

    p  = phase+poff;			// offset phase
    dp = freq*dt;			// delta phase
    ddp = chirp*dt*dt;  		// delta phase delta

    if (poff!=0) p -= Math.floor(p);	// modulo 1.0 if necessary
    if (dp<0 && shape!=SIN) dp = -dp;	// no negative freqs except for SINs

    switch (shape) {			// branch on wave shape
      case SIN: Waveform.sincos(fbuf,amp,p,dp,ndo,mode); break;
      case SQU: Waveform.square(fbuf,amp,p,dp,ndo,mode); break;
      case TRI: Waveform.triangle(fbuf,amp,p,dp,ndo,mode); break;
      case SAW: Waveform.sawtooth(fbuf,amp,p,dp,ndo,mode); break;
      case PUL: Waveform.pulse(fbuf,amp,p,dp,ndo,mode); break;
      case CON: Waveform.constant(fbuf,amp,ndo,mode); break;
      case ZER: Waveform.constant(fbuf,0.0,ndo,mode); break;
      case WHI: Waveform.whitenoise(fbuf,amp,ndo,mode); break;
      case RAM: Waveform.sawtooth(fbuf,amp,p,dp,ndo,mode); break;
    }

    data.uncast(fbuf,true);
    if (throttle==REALTIME) Time.sleep( dt*ndo );
    hcb.write(data,ndo);

    phase += dp*ndo;			// increment phase
    phase -= Math.floor(phase);		// modulo 1.0

    return (NORMAL);
  }

  public int close() {
    hcb.close();
    return (NORMAL);
  }

  public int restart() {
    hcb.close();
    hcb = MA.getDataFile("OUT",hcb,0); 
    hcb.setFormat (MA.getS("FORM"),"S#,C#");
    hcb.setSize (todo);
    hcb.open();
    data = hcb.getDataBuffer(xfer,FLOAT);
    return (NORMAL);
  }

  /** set run-time properties */
  public void setShape (String value) { 
    shape = Parser.find(shapeList,value,shape); 
  }
  public void setAmp (double value) { amp = value; }
  public void setFreq (double value) { freq = value; }
  public void setChirp (double value) { chirp = value; }
  public void setPhase (double value) { phase = value; }
  public void setThrottle (String value) { 
    throttle = Parser.find(throttleList,value,throttle); 
  }
  public void setFormat (String format) {
    MA.put("FORM",format); setState(RESTART);
  }

  /** get run-time properties */
  public String getShape () { return Parser.get(shapeList,shape); }
  public double getAmp () { return amp; }
  public double getFreq () { return freq; }
  public double getChirp () { return chirp; }
  public double getPhase () { return phase; }
  public String getThrottle () { return Parser.get(throttleList,throttle); }
  public String getFormat () { return MA.getS("FORM"); }

}