{ Simulates a triple RC network filter on a PWM-signal
  generated with an AVR (8/9/10-bit
  Written in Pascal for a Free Pascal command line
  (C)2003 by www.avr-asm-tutorial.net }
Program avr_pwm;

Uses Crt,Dos;

Var nb:Byte;
  ns:LongInt;
  fq,r,c:Extended;
  ua,ue,u1,u2,u3,ut,p:Extended;
  ch:Char;

Procedure Select_Steps;
Begin
Repeat
  Writeln;
  Write('Approximation steps: ');
  Readln(ns);
  Until (ns>=1);
End;

Procedure Select_Bits;
Begin
Repeat
  Writeln;
  Write('8, 9 or 10 bit PWM : ');
  Readln(nb);
  Until (nb>=8) And (nb<=10);
Case nb Of
  8:ut:=2.5/255*1000;
  9:ut:=2.5/511*1000;
  10:ut:=2.5/1023*1000;
  End;
End;

Procedure Select_Frequ;
Begin
Writeln;
Write('XTal frequency in Mcs/s: ');
Readln(fq);
End;

Procedure Select_R;
Begin
Writeln;
Write('Value for R in kiloohm: ');
Readln(r);
End;

Procedure Select_C;
Begin
Writeln;
Write('Value for C in nano-Farad: ');
Readln(c);
End;

Procedure Select_Pulse;
Var cd:Char;
  cs:Char;
  cc:Char;
  nTop:Extended;
Begin
Writeln;
Repeat
  Write('<i>nitial step, <f>irst or <l>ast approximation step ... ');
  cs:=UpCase(Readkey);
  Until (cs='F') Or (cs='L') Or (cs='I');
Writeln(cs);
If cs='L' Then
  Begin
  Repeat
    Write('<h>ighest or <l>owest limit ... ');
    cc:=UpCase(Readkey);
    Until (cs='H') Or (cs='L');
  Writeln(cc);
  End;
Repeat
  Write('<u>p- or <d>own-step ... ');
  cd:=UpCase(Readkey);
  Until (cd='U') Or (cd='D');
Writeln(cd);
Case cs Of
  'F': Begin
    ua:=2.500;
    If cd='U' Then p:=75 Else p:=25;
    End;
  'L': Begin
    Case nb Of
      8:nTop:=255.0;
      9:nTop:=511.0;
      10:nTop:=1023.0;
      End;
    If cc='H' Then
      Begin
      Ua:=(nTop-1.0)/nTop*5.0;
      If cd='U' Then p:=100 Else p:=(nTop-2)/nTop*100;
      End Else
      Begin
      Ua:=2/nTop*5.0;
      If cd='U' Then p:=3/nTop*100.0 Else p:=1/nTop*100.0;
      End;
    End;
  'I': Begin
    p:=50;
    If cd='U' Then Ua:=0.0 Else Ua:=5.00;
	End;
  End;
ue:=p/100.0*5.0;
End;

Procedure Header;
Begin
Writeln;
Writeln('Phase Pulse    t(ms)    U1(V)    U2(V)    U3(V)   Ud(mV)   Uf(mV)');
Writeln('----- ----- -------- -------- -------- -------- -------- --------');
End;

Procedure Execute;
Var k,n:LongInt;
  ch:Char;
  ud,uf,uh1,uh2,uh3,tcuh,tcul:Extended;
  fpwm,tpwm,tph,tpl,tms:Extended;
Begin
Case nb Of
  8:fpwm:=fq*1E6/510;
  9:fpwm:=fq*1E6/1022;
  10:fpwm:=fq*1E6/2046;
  End;
tpwm:=1E6/fpwm; { duration of PWM cycle in us }
tph:=p*tpwm/100; { duration of high cycle in us }
tpl:=tpwm-tph; { duration of low cycle in us }
tcuh:=tph/r/c/ns;
tcul:=tpl/r/c/ns;
{ Writeln('tph=',tph);
Writeln('tpl=',tpl);
Writeln('tcuh=',tcuh);
Writeln('tcul=',tcul); debug code }
u1:=ua;
u2:=ua;
u3:=ua;
n:=0;
tms:=0.0;
ud:=0.0;
uf:=(ua-ue)*1000;
Header;
Writeln('start',n:6,tms:9:3,u1:9:5,U2:9:5,U3:9:5,ud:9:2,uf:9:2);
Repeat
  Inc(n);
{  Writeln('Up-step'); Debug code }
  ud:=u3;
  For k:=1 To ns Do  { High period }
    Begin
    uh1:=(5.0-u1+u2-u1)*tcuh;
    uh2:=(u1-u2+u3-u2)*tcuh;
    uh3:=(u2-u3)*tcuh;
{    Writeln('uh1=',uh1,' uh2=',uh2,' uh3=',uh3);
    Repeat Until Keypressed;
    ch:=ReadKey; Debug code }
    u1:=u1+uh1;
    u2:=u2+uh2;
    u3:=u3+uh3;
    End;
{  Writeln('    h:',u1:9:4,U2:9:4,U3:9:4);
  Writeln('Dwn-step'); Debug code }
  ud:=(u3-ud)*1000;
  uf:=(u3-ue)*1000;
  tms:=(n-0.5)*tpwm/1000.0;
  Writeln(' high',n:6,tms:9:3,u1:9:5,U2:9:5,U3:9:5,ud:9:2,uf:9:2);
  ud:=u3;
  For k:=1 To ns Do
    Begin
    uh1:=(0.0-u1+u2-u1)*tcul;
    uh2:=(u1-u2+u3-u2)*tcul;
    uh3:=(u2-u3)*tcul;
{    Writeln('uh1=',uh1,' uh2=',uh2,' uh3=',uh3);
    Repeat Until Keypressed;
    ch:=ReadKey; }
    u1:=u1+uh1;
    u2:=u2+uh2;
    u3:=u3+uh3;
    End;
  ud:=(u3-ud)*1000;
  uf:=(u3-ue)*1000;
  tms:=n*tpwm/1000.0;
  If (n Mod 10)=0 Then Header;
  Write('  low',n:6,tms:9:3,u1:9:5,U2:9:5,U3:9:5,ud:9:2,uf:9:2,'  e<x>ec... ');
  ch:=UpCase(Readkey);
  Writeln(ch);
  Until ch<>'X';
End;

Begin
ns:=10000;
nb:=8;
fq:=4.0;
r:=10.0;
c:=100.0;
ua:=2.5;
ue:=3.75;
ut:=2.5/255*1000;
fq:=4;
p:=75;
ClrScr;
Repeat
  Writeln;
  Writeln('====> avr_pwm1, Simulation of a triple RC network filter (C)2003 DG4FAC <=====');
  Writeln('                                      PWM <b>it resolution = ',nb,'-bit');
  Writeln('      ___  U1   ___  U2   ___  U3     AVR clock <f>requency = ',fq:7:3,' Mcs/s');
  Writeln(' O---|___|--o--|___|--o--|___|--o--O  Simulation <s>teps per PWM cycle = ',ns);
  Writeln(' PWM   R    |    R    |    R    |  Ue <R>esistors = ',r:6:0,' kOhm');
  Writeln('           ---       ---       ---    <C>apacitors = ',c:6:0,' nF');
  Writeln('         C ---     C ---     C ---    Start <v>oltage Ua = ',ua:7:5,' V');
  Writeln('            |         |         |     End <v>oltage Ue = ',ue:7:5,' V');
  Writeln('           ---       ---       ---    U Delta Tolerable = ',ut:7:2,' mV');
  Write('                                      e<x>ecute, <ESC> ... ');
  ch:=Upcase(Readkey);
  Writeln(ch);
  Case ch Of
    'S':Select_Steps;
    'B':Select_Bits;
    'F':Select_Frequ;
    'R':Select_R;
    'C':Select_C;
    'V':Select_Pulse;
    'X':Execute;
    End;
  Until ch=Char(27);
End.
