//VerilogA for passive,wgstroptilen,veriloga

`include "constants.vams"
`include "disciplines.vams"

module wgstroptilen(Ipow,Iphase,Ilam,Opow,Ophase,Olam);
    parameter integer modespec = 1 from [1:2];
    parameter real optlength_te = 1e-3 from [0:inf);
    parameter real optlength_tm = 1e-3 from [0:inf);
    parameter real optloss_te = 0 from [0:inf);
    parameter real optloss_tm = 0 from [0:inf);
    parameter real phasedelay_te = 0;
    parameter real phasedelay_tm = 0;

    input Ipow,Iphase,Ilam;
    output Opow,Ophase,Olam;
    electrical Ipow,Iphase,Ilam,Opow,Ophase,Olam;

    real eeir,eeii,emir,emii;
    real eeor,eeoi,emor,emoi;
    real t11r,t11i,t12r,t12i,t21r,t21i,t22r,t22i;
    real iph;

    analog begin
        iph=V(Iphase)/360.0*2*`M_PI;
        if (modespec == 1) begin
            eeir=sqrt(V(Ipow))*cos(iph);
            eeii=sqrt(V(Ipow))*sin(iph);
            emir=0;
            emii=0;
        end
        else if (modespec == 2) begin
            eeir=0;
            eeii=0;
            emir=sqrt(V(Ipow))*cos(iph);
            emii=sqrt(V(Ipow))*sin(iph);
        end

        //calc transfer matrix
        t11r=pow(10,-optloss_te/20)*cos(phasedelay_te/360.0*2*`M_PI-2*`M_PI/V(Ilam)*optlength_te);
        t11i=pow(10,-optloss_te/20)*sin(phasedelay_te/360.0*2*`M_PI-2*`M_PI/V(Ilam)*optlength_te);
        t12r=0;
        t12i=0;
        t21r=0;
        t21i=0;
        t22r=pow(10,-optloss_tm/20)*cos(phasedelay_tm/360.0*2*`M_PI-2*`M_PI/V(Ilam)*optlength_tm);
        t22i=pow(10,-optloss_tm/20)*sin(phasedelay_tm/360.0*2*`M_PI-2*`M_PI/V(Ilam)*optlength_tm);

        eeor=t11r*eeir-t11i*eeii+t12r*emir-t12i*emii;
        eeoi=t11r*eeii+t11i*eeir+t12r*emii+t12i*emir;
        emor=t21r*eeir-t21i*eeii+t22r*emir-t22i*emii;
        emoi=t21r*eeii+t21i*eeir+t22r*emii+t22i*emir;

        V(Olam) <+ V(Ilam);
        if (modespec == 1) begin
            V(Opow) <+ eeor*eeor+eeoi*eeoi;
            V(Ophase) <+ atan2(eeoi,eeor)*360.0/(2*`M_PI);
        end
        else if (modespec == 2) begin
            V(Opow) <+ emor*emor+emoi*emoi;
            V(Ophase) <+ atan2(emoi,emor)*360.0/(2*`M_PI);
        end
    end

endmodule