Main Page | Class List | File List | Class Members | File Members

unMain.cpp

Go to the documentation of this file.
00001 /*
00002  *  $Id: unMain.cpp,v 1.18 2006/09/11 10:10:23 ghost666 Exp $
00003  *
00004  *  OpAmpSim - Operational amplifier simulator
00005  *  Copyright (C) 2006 Piotr 'GhosT' Wydrych,
00006  *                     Krzystof Rusek,
00007  *                     Grzegorz Gancarczyk
00008  *
00009  *  This program is free software; you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation; either version 2 of the License, or
00012  *  (at your option) any later version.
00013  *
00014  *  This program is distributed in the hope that it will be useful,
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with this program; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022  */
00023 
00024 //---------------------------------------------------------------------------
00025 
00026 #include <vcl.h>
00027 #pragma hdrstop
00028 
00029 #include "unMain.h"
00030 //---------------------------------------------------------------------------
00031 #pragma package(smart_init)
00032 #pragma resource "*.dfm"
00033 TfmMain *fmMain;
00034 //---------------------------------------------------------------------------
00035 
00036 long round(double x)
00037 {
00038         double t;
00039 
00040         if (x >= 0.0) {
00041                 t = floor(x);
00042                 if (t - x <= -0.5)
00043                         t += 1.0;
00044                 return (long)(t);
00045         } else {
00046                 t = floor(-x);
00047                 if (t + x <= -0.5)
00048                         t += 1.0;
00049                 return (long)(-t);
00050         }
00051 }
00052 //---------------------------------------------------------------------------
00053 
00054 void merge(double *array, size_t start, size_t mid, size_t stop)
00055 {
00056         double *array_out = new double[stop-start+1];
00057         size_t i1, i2, io, k;
00058         i1 = start;
00059         i2 = mid+1;
00060         io = 0;
00061         while ((i1 <= mid) && (i2 <= stop))
00062                 if (array[i1] < array[i2])
00063                         array_out[io++] = array[i1++];
00064                 else
00065                         array_out[io++] = array[i2++];
00066 
00067         if (i1 > mid)
00068                 for (k = i2; k <= stop; ++k, ++io)
00069                         array_out[io] = array[k];
00070         else
00071                 for (k = i1; k <= mid; ++k, ++io)
00072                         array_out[io] = array[k];
00073 
00074         for (k = start; k <= stop; ++k)
00075                 array[k] = array_out[k-start];
00076 
00077         delete[] array_out;
00078 }
00079 
00080 void merge_sort(double *array, size_t start, size_t stop)
00081 {
00082         if (start == stop) return;
00083         else
00084         {
00085                 size_t mid = (start+stop)/2;
00086                 merge_sort(array, start, mid);
00087                 merge_sort(array, mid+1, stop);
00088                 merge(array, start, mid, stop);
00089         }
00090 }
00091 //---------------------------------------------------------------------------
00092 
00093 __fastcall TfmMain::TfmMain(TComponent* Owner)
00094             : TForm(Owner)
00095 {
00096         unsigned short int i;
00097         TStringList* StringList = new TStringList();
00098 
00099         imSchematic->Picture->Bitmap = new Graphics::TBitmap();
00100         imSchematic->Picture->Bitmap->LoadFromResourceName((int)HInstance, "SCHEMA");
00101 
00102         // initialise Z1, Z2 & H
00103         Z1 = new TTransferFunction;
00104         Z2 = new TTransferFunction;
00105         H = new TTransferFunction;
00106         Z1->NumeratorPulsationsCount = Z2->NumeratorPulsationsCount = H->NumeratorPulsationsCount = 0;
00107         Z1->DenominatorPulsationsCount = Z2->DenominatorPulsationsCount = H->DenominatorPulsationsCount = 0;
00108 
00109         // initialise PlotArea properties
00110         PlotArea = new TPlotAreaProperties;
00111         PlotArea->ScaleX = new TScale;
00112         PlotArea->ScaleY = new TScale;
00113         PlotArea->Height = pbGraph->Height;
00114         PlotArea->Width = pbGraph->Width;
00115         PlotArea->ScaleX->Min = 1; // sample values
00116         PlotArea->ScaleX->Max = 5; // from 10 to 100k
00117 
00118         // plots
00119         UncorrectedBodePlot = new TPlot;
00120         CorrectedBodePlot = new TPlot;
00121         // in RecalcPlots memory is freed, so we must alloc to free
00122         UncorrectedBodePlot->X = new double[1];
00123         UncorrectedBodePlot->Y = new double[1];
00124         CorrectedBodePlot->X = new double[1];
00125         CorrectedBodePlot->Y = new double[1];
00126 
00127         // psValuesR descendants init
00128 
00129         StringList->Add("zwarcie");
00130         for (i = 0; i < ARRAYSIZE(ValuesRm); ++i)
00131         {
00132                 StringList->Add(AnsiString::FormatFloat("0.0", ValuesRm[i]));
00133         }
00134         StringList->Add("rozwarcie");
00135         cbValuesR11m->Items->Assign(StringList); cbValuesR11m->DropDownCount = cbValuesR11m->Items->Count;
00136         cbValuesR12m->Items->Assign(StringList); cbValuesR12m->DropDownCount = cbValuesR12m->Items->Count;
00137         cbValuesR21m->Items->Assign(StringList); cbValuesR21m->DropDownCount = cbValuesR21m->Items->Count;
00138         cbValuesR22m->Items->Assign(StringList); cbValuesR22m->DropDownCount = cbValuesR22m->Items->Count;
00139 
00140         tbValuesR11->Max = 1 + (ARRAYSIZE(ValuesRm)) * (ARRAYSIZE(ValuesReVal));
00141         tbValuesR11->PageSize = ARRAYSIZE(ValuesRm);
00142         tbValuesR11->Frequency = ARRAYSIZE(ValuesRm) / 2;
00143         tbValuesR12->Max = tbValuesR11->Max; tbValuesR12->PageSize = tbValuesR11->PageSize; tbValuesR12->Frequency = tbValuesR11->Frequency;
00144         tbValuesR21->Max = tbValuesR11->Max; tbValuesR21->PageSize = tbValuesR11->PageSize; tbValuesR21->Frequency = tbValuesR11->Frequency;
00145         tbValuesR22->Max = tbValuesR11->Max; tbValuesR22->PageSize = tbValuesR11->PageSize; tbValuesR22->Frequency = tbValuesR11->Frequency;
00146 
00147         StringList->Clear();
00148 
00149         for (i = 0; i < ARRAYSIZE(ValuesReTxt); ++i)
00150                 StringList->Add(ValuesReTxt[i]);
00151         cbValuesR11e->Items->Assign(StringList); cbValuesR11e->DropDownCount = cbValuesR11e->Items->Count;
00152         cbValuesR12e->Items->Assign(StringList); cbValuesR12e->DropDownCount = cbValuesR12e->Items->Count;
00153         cbValuesR21e->Items->Assign(StringList); cbValuesR21e->DropDownCount = cbValuesR21e->Items->Count;
00154         cbValuesR22e->Items->Assign(StringList); cbValuesR22e->DropDownCount = cbValuesR22e->Items->Count;
00155 
00156         StringList->Clear();
00157 
00158         StringList->Add("rozwarcie");
00159         for (i = 0; i < ARRAYSIZE(ValuesCm); ++i)
00160         {
00161                 StringList->Add(AnsiString::FormatFloat("0.0", ValuesCm[i]));
00162         }
00163         StringList->Add("zwarcie");
00164         cbValuesC11m->Items->Assign(StringList); cbValuesC11m->DropDownCount = cbValuesC11m->Items->Count;
00165         cbValuesC12m->Items->Assign(StringList); cbValuesC12m->DropDownCount = cbValuesC12m->Items->Count;
00166         cbValuesC21m->Items->Assign(StringList); cbValuesC21m->DropDownCount = cbValuesC21m->Items->Count;
00167         cbValuesC22m->Items->Assign(StringList); cbValuesC22m->DropDownCount = cbValuesC22m->Items->Count;
00168 
00169         tbValuesC11->Max = 1 + ARRAYSIZE(ValuesCm) * ARRAYSIZE(ValuesCeVal);
00170         tbValuesC11->PageSize = ARRAYSIZE(ValuesCm);
00171         tbValuesC11->Frequency = ARRAYSIZE(ValuesCm) / 2;
00172         tbValuesC12->Max = tbValuesC11->Max; tbValuesC12->PageSize = tbValuesC11->PageSize; tbValuesC12->Frequency = tbValuesC11->Frequency;
00173         tbValuesC21->Max = tbValuesC11->Max; tbValuesC21->PageSize = tbValuesC11->PageSize; tbValuesC21->Frequency = tbValuesC11->Frequency;
00174         tbValuesC22->Max = tbValuesC11->Max; tbValuesC22->PageSize = tbValuesC11->PageSize; tbValuesC22->Frequency = tbValuesC11->Frequency;
00175 
00176         StringList->Clear();
00177 
00178         for (i = 0; i < ARRAYSIZE(ValuesCeTxt); ++i)
00179                 StringList->Add(ValuesCeTxt[i]);
00180         cbValuesC11e->Items->Assign(StringList); cbValuesC11e->DropDownCount = cbValuesC11e->Items->Count;
00181         cbValuesC12e->Items->Assign(StringList); cbValuesC12e->DropDownCount = cbValuesC12e->Items->Count;
00182         cbValuesC21e->Items->Assign(StringList); cbValuesC21e->DropDownCount = cbValuesC21e->Items->Count;
00183         cbValuesC22e->Items->Assign(StringList); cbValuesC22e->DropDownCount = cbValuesC22e->Items->Count;
00184 
00185         delete StringList;
00186 
00187         // some sample values for Rs
00188 
00189         cbValuesR11m->ItemIndex=1;                              // 1.0       |
00190         cbValuesR11e->ItemIndex=4;                              // 10 *kOhm  | 10 kOhm
00191         cbValuesR12m->ItemIndex=cbValuesR12m->Items->Count - 1; // +oo
00192         cbValuesR12e->ItemIndex=0;                              // may be Ohm, doesn't matter
00193         cbValuesR21m->ItemIndex=cbValuesR21m->Items->Count - 1; // +oo
00194         cbValuesR21e->ItemIndex=0;                              // may be Ohm, doesn't matter
00195         cbValuesR22m->ItemIndex=1;                              // 1.0   |
00196         cbValuesR22e->ItemIndex=6;                              // MOhm  | 1 MOhm
00197 
00198         // some sample values for Cs
00199 
00200         cbValuesC11m->ItemIndex=2;                              // 1.5    |
00201         cbValuesC11e->ItemIndex=4;                              // 10*nF  | 15 nF
00202         cbValuesC12m->ItemIndex=0;                              // 0 (X = +oo)
00203         cbValuesC12e->ItemIndex=0;                              // may be pF, doesn't matter
00204         cbValuesC21m->ItemIndex=0;                              // 0 (X = +oo)
00205         cbValuesC21e->ItemIndex=0;                              // may be pF, doesn't matter
00206         cbValuesC22m->ItemIndex=2;                              // 1.5    |
00207         cbValuesC22e->ItemIndex=2;                              // 100*pF | 150 pF
00208 
00209         // calculate trackbars positions for Rs
00210 
00211         cbValuesRChange(cbValuesR11m);
00212         cbValuesRChange(cbValuesR12m);
00213         cbValuesRChange(cbValuesR21m);
00214         cbValuesRChange(cbValuesR22m);
00215 
00216         // calculate trackbars positions for Cs
00217 
00218         cbValuesCChange(cbValuesC11m);
00219         cbValuesCChange(cbValuesC12m);
00220         cbValuesCChange(cbValuesC21m);
00221         cbValuesCChange(cbValuesC22m);
00222 }
00223 //---------------------------------------------------------------------------
00224 
00225 void __fastcall TfmMain::cbValuesRChange(TObject *Sender)
00226 {
00227         // function for all 4 resitors
00228         TComboBox *cbValuesRm; // cbValuesR11m or cbValuesR12m or cbValuesR21m or cbValuesR22m
00229         TComboBox *cbValuesRe; // cbValuesR11e or cbValuesR12e or cbValuesR21e or cbValuesR22e
00230         TTrackBar *tbValuesR;  // tbValuesR11  or tbValuesR12  or tbValuesR21  or tbValuesR22
00231 
00232         if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesR11m")
00233             || !AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesR11e"))
00234         {
00235                 cbValuesRm = cbValuesR11m;
00236                 cbValuesRe = cbValuesR11e;
00237                 tbValuesR  = tbValuesR11;
00238                 Z1->OK = UpdateImpedance(1);
00239         }
00240         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesR12m")
00241                  || !AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesR12e"))
00242         {
00243                 cbValuesRm = cbValuesR12m;
00244                 cbValuesRe = cbValuesR12e;
00245                 tbValuesR  = tbValuesR12;
00246                 Z1->OK = UpdateImpedance(1);
00247         }
00248         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesR21m")
00249                  || !AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesR21e"))
00250         {
00251                 cbValuesRm = cbValuesR21m;
00252                 cbValuesRe = cbValuesR21e;
00253                 tbValuesR  = tbValuesR21;
00254                 Z2->OK = UpdateImpedance(2);
00255         }
00256         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesR22m")
00257                  || !AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesR22e"))
00258         {
00259                 cbValuesRm = cbValuesR22m;
00260                 cbValuesRe = cbValuesR22e;
00261                 tbValuesR  = tbValuesR22;
00262                 Z2->OK = UpdateImpedance(2);
00263         }
00264         else
00265                 return;
00266 
00267         if (cbValuesRm->ItemIndex == 0) // R = 0
00268                 tbValuesR->Position = 0;
00269         else if  (cbValuesRm->ItemIndex == cbValuesRm->Items->Count - 1) //R = +oo
00270                 tbValuesR->Position = tbValuesR->Max;
00271         else
00272                 tbValuesR->Position = cbValuesRm->ItemIndex + cbValuesRe->ItemIndex * ARRAYSIZE(ValuesRm);
00273         cbValuesRe->Enabled = (cbValuesRm->ItemIndex != 0) && (cbValuesRm->ItemIndex != cbValuesRm->Items->Count - 1);
00274 
00275         UpdateTransferFunction();
00276         RecalcPlots();
00277         pbGraph->Repaint();
00278         pbScaleY->Repaint();
00279 }
00280 //---------------------------------------------------------------------------
00281 
00282 void __fastcall TfmMain::tbValuesRChange(TObject *Sender)
00283 {
00284         // function for all 4 resitors
00285         TComboBox *cbValuesRm; // cbValuesR11m or cbValuesR12m or cbValuesR21m or cbValuesR22m
00286         TComboBox *cbValuesRe; // cbValuesR11e or cbValuesR12e or cbValuesR21e or cbValuesR22e
00287         TTrackBar *tbValuesR;  // tbValuesR11  or tbValuesR12  or tbValuesR21  or tbValuesR22
00288 
00289         if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "tbValuesR11"))
00290         {
00291                 cbValuesRm = cbValuesR11m;
00292                 cbValuesRe = cbValuesR11e;
00293                 tbValuesR  = tbValuesR11;
00294                 Z1->OK = UpdateImpedance(1);
00295         }
00296         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "tbValuesR12"))
00297         {
00298                 cbValuesRm = cbValuesR12m;
00299                 cbValuesRe = cbValuesR12e;
00300                 tbValuesR  = tbValuesR12;
00301                 Z1->OK = UpdateImpedance(1);
00302         }
00303         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "tbValuesR21"))
00304         {
00305                 cbValuesRm = cbValuesR21m;
00306                 cbValuesRe = cbValuesR21e;
00307                 tbValuesR  = tbValuesR21;
00308                 Z2->OK = UpdateImpedance(2);
00309         }
00310         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "tbValuesR22"))
00311         {
00312                 cbValuesRm = cbValuesR22m;
00313                 cbValuesRe = cbValuesR22e;
00314                 tbValuesR  = tbValuesR22;
00315                 Z2->OK = UpdateImpedance(2);
00316         }
00317         else
00318                 return;
00319 
00320         if (tbValuesR->Position == 0) // R = 0
00321                 cbValuesRm->ItemIndex = 0;
00322         else if (tbValuesR->Position == tbValuesR->Max) // R = +oo
00323                 cbValuesRm->ItemIndex = cbValuesRm->Items->Count - 1;
00324         else
00325         {
00326                 cbValuesRm->ItemIndex = 1 + (tbValuesR->Position - 1) % (ARRAYSIZE(ValuesRm));
00327                 cbValuesRe->ItemIndex = (tbValuesR->Position - 1) / (ARRAYSIZE(ValuesRm));
00328         }
00329         cbValuesRe->Enabled = (tbValuesR->Position != 0) && (tbValuesR->Position != tbValuesR->Max);
00330 
00331         UpdateTransferFunction();
00332         RecalcPlots();
00333         pbGraph->Repaint();
00334         pbScaleY->Repaint();
00335 }
00336 //---------------------------------------------------------------------------
00337 
00338 void __fastcall TfmMain::cbValuesCChange(TObject *Sender)
00339 {
00340         // function for all 4 capacitors
00341         TComboBox *cbValuesCm; // cbValuesC11m or cbValuesC12m or cbValuesC21m or cbValuesC22m
00342         TComboBox *cbValuesCe; // cbValuesC11e or cbValuesC12e or cbValuesC21e or cbValuesC22e
00343         TTrackBar *tbValuesC;  // tbValuesC11  or tbValuesC12  or tbValuesC21  or tbValuesC22
00344 
00345         if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesC11m")
00346             || !AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesC11e"))
00347         {
00348                 cbValuesCm = cbValuesC11m;
00349                 cbValuesCe = cbValuesC11e;
00350                 tbValuesC  = tbValuesC11;
00351                 Z1->OK = UpdateImpedance(1);
00352         }
00353         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesC12m")
00354                  || !AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesC12e"))
00355         {
00356                 cbValuesCm = cbValuesC12m;
00357                 cbValuesCe = cbValuesC12e;
00358                 tbValuesC  = tbValuesC12;
00359                 Z1->OK = UpdateImpedance(1);
00360         }
00361         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesC21m")
00362                  || !AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesC21e"))
00363         {
00364                 cbValuesCm = cbValuesC21m;
00365                 cbValuesCe = cbValuesC21e;
00366                 tbValuesC  = tbValuesC21;
00367                 Z2->OK = UpdateImpedance(2);
00368         }
00369         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesC22m")
00370                  || !AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "cbValuesC22e"))
00371         {
00372                 cbValuesCm = cbValuesC22m;
00373                 cbValuesCe = cbValuesC22e;
00374                 tbValuesC  = tbValuesC22;
00375                 Z2->OK = UpdateImpedance(2);
00376         }
00377         else
00378                 return;
00379 
00380         if (cbValuesCm->ItemIndex == 0) // C = 0
00381                 tbValuesC->Position = 0;
00382         else if  (cbValuesCm->ItemIndex == cbValuesCm->Items->Count - 1) // C = +oo
00383                 tbValuesC->Position = tbValuesC->Max;
00384         else
00385                 tbValuesC->Position = cbValuesCm->ItemIndex + cbValuesCe->ItemIndex * ARRAYSIZE(ValuesCm);
00386         cbValuesCe->Enabled = (cbValuesCm->ItemIndex != 0) && (cbValuesCm->ItemIndex != cbValuesCm->Items->Count - 1);
00387 
00388         UpdateTransferFunction();
00389         RecalcPlots();
00390         pbGraph->Repaint();
00391         pbScaleY->Repaint();
00392 }
00393 //---------------------------------------------------------------------------
00394 
00395 void __fastcall TfmMain::tbValuesCChange(TObject *Sender)
00396 {
00397         // function for all 4 resitors
00398         TComboBox *cbValuesCm; // cbValuesC11m or cbValuesC12m or cbValuesC21m or cbValuesC22m
00399         TComboBox *cbValuesCe; // cbValuesC11e or cbValuesC12e or cbValuesC21e or cbValuesC22e
00400         TTrackBar *tbValuesC;  // tbValuesC11  or tbValuesC12  or tbValuesC21  or tbValuesC22
00401 
00402         if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "tbValuesC11"))
00403         {
00404                 cbValuesCm = cbValuesC11m;
00405                 cbValuesCe = cbValuesC11e;
00406                 tbValuesC  = tbValuesC11;
00407                 Z1->OK = UpdateImpedance(1);
00408         }
00409         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "tbValuesC12"))
00410         {
00411                 cbValuesCm = cbValuesC12m;
00412                 cbValuesCe = cbValuesC12e;
00413                 tbValuesC  = tbValuesC12;
00414                 Z1->OK = UpdateImpedance(1);
00415         }
00416         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "tbValuesC21"))
00417         {
00418                 cbValuesCm = cbValuesC21m;
00419                 cbValuesCe = cbValuesC21e;
00420                 tbValuesC  = tbValuesC21;
00421                 Z2->OK = UpdateImpedance(2);
00422         }
00423         else if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "tbValuesC22"))
00424         {
00425                 cbValuesCm = cbValuesC22m;
00426                 cbValuesCe = cbValuesC22e;
00427                 tbValuesC  = tbValuesC22;
00428                 Z2->OK = UpdateImpedance(2);
00429         }
00430         else
00431                 return;
00432 
00433         if (tbValuesC->Position == 0) // C = 0
00434                 cbValuesCm->ItemIndex = 0;
00435         else if (tbValuesC->Position == tbValuesC->Max) // C = +oo
00436                 cbValuesCm->ItemIndex = cbValuesCm->Items->Count - 1;
00437         else
00438         {
00439                 cbValuesCm->ItemIndex = 1 + (tbValuesC->Position - 1) % (ARRAYSIZE(ValuesCm));
00440                 cbValuesCe->ItemIndex = (tbValuesC->Position - 1) / (ARRAYSIZE(ValuesCm));
00441         }
00442         cbValuesCe->Enabled = (tbValuesC->Position != 0) && (tbValuesC->Position != tbValuesC->Max);
00443 
00444         UpdateTransferFunction();
00445         RecalcPlots();
00446         pbGraph->Repaint();
00447         pbScaleY->Repaint();
00448 }
00449 //---------------------------------------------------------------------------
00450 
00451 void __fastcall TfmMain::CalcUncorrectedBodePlot(unsigned int pulsationsCount, double *pulsations, double *out)
00452 {
00453         unsigned int i, j;
00454         // slope [dB per decade]
00455         double* slope = new double[pulsationsCount];
00456 
00457         slope[0] = H->b * 20;
00458         for(i = 1; i < pulsationsCount; ++i)
00459         {
00460                 slope[i] = slope[i-1];
00461                 //increase angle in every zero
00462                 for(j=0; j < H->NumeratorPulsationsCount; ++j)
00463                         if (H->NumeratorPulsations[j] == pulsations[i-1])
00464                                 slope[i] += 20;
00465                 //decrease angle in every pole
00466                 for(j=0; j < H->DenominatorPulsationsCount; ++j)
00467                         if (H->DenominatorPulsations[j] == pulsations[i-1])
00468                                 slope[i] -= 20;
00469         }
00470 
00471         out[0] = 20 * log10l(fabs(H->A)) + slope[0] * log10l(pulsations[0]);
00472         for(i = 1; i < pulsationsCount; ++i)
00473                 out[i] = out[i-1] + slope[i] * (log10l(pulsations[i]) - log10l(pulsations[i-1]));
00474 
00475         delete[] slope;
00476 }
00477 //---------------------------------------------------------------------------
00478 
00479 void __fastcall TfmMain::CalcCorrectedBodePlot(unsigned int pulsationsCount, double *pulsations, double *out)
00480 {
00481         // dB value
00482         double DB;
00483         unsigned int i, j;
00484 
00485         if (!H->OK) return;
00486 
00487         //main loop for all pulsations
00488         for(i = 0; i < pulsationsCount; ++i)
00489         {
00490                 DB = 20 * log10l(fabs(H->A)) + 20 * (H->b) * log10l(pulsations[i]);
00491                 //numerator
00492                 for(j = 0; j< H->NumeratorPulsationsCount; j++)
00493                         DB += 10*log10l(1 + pulsations[i] * pulsations[i] / (H->NumeratorPulsations[j] * H->NumeratorPulsations[j]));
00494 
00495                 //denominator
00496                 for(j = 0; j< H->DenominatorPulsationsCount; j++)
00497                         DB -= 10 * log10l(1 + pulsations[i] * pulsations[i] / (H->DenominatorPulsations[j] * H->DenominatorPulsations[j]));
00498 
00499                 out[i] = DB;
00500         }
00501 }
00502 //---------------------------------------------------------------------------
00503 
00504 bool __fastcall TfmMain::UpdateImpedance(unsigned short int id)
00505 {
00506         // id = 0 - do nothing
00507         // id = 1 - update Z1
00508         // id = 2 - update Z2
00509         // id = 3 - update both by calling itself twice
00510 
00511         TComboBox *cbValuesR1m; // cbValuesR11m or cbValuesR21m
00512         TComboBox *cbValuesR1e; // cbValuesR11e or cbValuesR21e
00513         TComboBox *cbValuesR2m; // cbValuesR12m or cbValuesR22m
00514         TComboBox *cbValuesR2e; // cbValuesR12e or cbValuesR22e
00515         TComboBox *cbValuesC1m; // cbValuesC11m or cbValuesC21m
00516         TComboBox *cbValuesC1e; // cbValuesC11e or cbValuesC21e
00517         TComboBox *cbValuesC2m; // cbValuesC12m or cbValuesC22m
00518         TComboBox *cbValuesC2e; // cbValuesC12e or cbValuesC22e
00519         PTransferFunction Z;    // Z1 or Z2
00520 
00521         double R1, R2, C1, C2;
00522         double a, b, c, d;
00523 
00524         if (id == 1)
00525         {
00526                 cbValuesR1m = cbValuesR11m;
00527                 cbValuesR1e = cbValuesR11e;
00528                 cbValuesR2m = cbValuesR12m;
00529                 cbValuesR2e = cbValuesR12e;
00530                 cbValuesC1m = cbValuesC11m;
00531                 cbValuesC1e = cbValuesC11e;
00532                 cbValuesC2m = cbValuesC12m;
00533                 cbValuesC2e = cbValuesC12e;
00534                 Z = Z1;
00535         }
00536         else if (id == 2)
00537         {
00538                 cbValuesR1m = cbValuesR21m;
00539                 cbValuesR1e = cbValuesR21e;
00540                 cbValuesR2m = cbValuesR22m;
00541                 cbValuesR2e = cbValuesR22e;
00542                 cbValuesC1m = cbValuesC21m;
00543                 cbValuesC1e = cbValuesC21e;
00544                 cbValuesC2m = cbValuesC22m;
00545                 cbValuesC2e = cbValuesC22e;
00546                 Z = Z2;
00547         }
00548         else if (id == 3)
00549                 return UpdateImpedance(1) && UpdateImpedance(2);
00550         else
00551                 return false;
00552 
00553         // old values are not needed any more
00554         if (Z->NumeratorPulsationsCount)
00555                 delete[] Z->NumeratorPulsations;
00556         if (Z->DenominatorPulsationsCount)
00557                 delete[] Z->DenominatorPulsations;
00558 
00559 
00560         // if Z = 0 return false
00561         if ((cbValuesR1m->ItemIndex == 0 && cbValuesC1m->ItemIndex == cbValuesC1m->Items->Count - 1)
00562             || cbValuesR2m->ItemIndex == 0
00563             || cbValuesC2m->ItemIndex == cbValuesC2m->Items->Count - 1)
00564                 return false;
00565 
00566         if (cbValuesR1m->ItemIndex != 0 && cbValuesR1m->ItemIndex != cbValuesR1m->Items->Count - 1)
00567                 R1 = ValuesRm[cbValuesR1m->ItemIndex - 1] * pow10(ValuesReVal[cbValuesR1e->ItemIndex]);
00568         if (cbValuesC1m->ItemIndex != 0 && cbValuesC1m->ItemIndex != cbValuesC1m->Items->Count - 1)
00569                 C1 = ValuesCm[cbValuesC1m->ItemIndex - 1] * pow10(ValuesCeVal[cbValuesC1e->ItemIndex]);
00570         if (cbValuesR2m->ItemIndex != 0 && cbValuesR2m->ItemIndex != cbValuesR2m->Items->Count - 1)
00571                 R2 = ValuesRm[cbValuesR2m->ItemIndex - 1] * pow10(ValuesReVal[cbValuesR2e->ItemIndex]);
00572         if (cbValuesC2m->ItemIndex != 0 && cbValuesC2m->ItemIndex != cbValuesC2m->Items->Count - 1)
00573                 C2 = ValuesCm[cbValuesC2m->ItemIndex - 1] * pow10(ValuesCeVal[cbValuesC2e->ItemIndex]);
00574 
00575         // if Z1 = +oo take info account R2 & C2
00576         if (cbValuesR1m->ItemIndex == cbValuesR1m->Items->Count - 1 || cbValuesC1m->ItemIndex == 0)
00577         {
00578                 // if Z2 = +oo return false
00579                 if (cbValuesR2m->ItemIndex == cbValuesR2m->Items->Count - 1 && cbValuesC2m->ItemIndex == 0)
00580                         return false;
00581 
00582                 // XC2 = +oo => Z = R2
00583                 if (cbValuesC2m->ItemIndex == 0)
00584                 {
00585                         Z->A = R2;
00586                         Z->b = 0;
00587                         Z->NumeratorPulsationsCount = 0;
00588                         Z->DenominatorPulsationsCount = 0;
00589                 }
00590 
00591                 // R2 = +oo => Z = 1/sC2
00592                 else if (cbValuesR2m->ItemIndex == cbValuesR2m->Items->Count - 1)
00593                 {
00594                         Z->A = 1 / C2;
00595                         Z->b = -1;
00596                         Z->NumeratorPulsationsCount = 0;
00597                         Z->DenominatorPulsationsCount = 0;
00598                 }
00599 
00600                 // both R2 and C2 exist
00601                 else
00602                 {
00603                         Z->A = R2;
00604                         Z->b = 0;
00605                         Z->NumeratorPulsationsCount = 0;
00606                         Z->DenominatorPulsationsCount = 1;
00607                         Z->DenominatorPulsations = new double[Z->DenominatorPulsationsCount];
00608                         Z->DenominatorPulsations[0] = 1 / (R2 * C2);
00609                 }
00610         }
00611 
00612         // XC1 = 0 => Z1 = R1
00613         else if (cbValuesC1m->ItemIndex == cbValuesC1m->Items->Count - 1)
00614         {
00615                 // R2 = +oo
00616                 if (cbValuesR2m->ItemIndex == cbValuesR2m->Items->Count - 1)
00617                         Z->A = R1;
00618                 else
00619                         Z->A = 1 / (1 / R1 + 1 / R2);
00620                 Z->b = 0;
00621                 Z->NumeratorPulsationsCount = 0;
00622 
00623                 // XC2 = +oo
00624                 if (cbValuesC1m->ItemIndex == 0)
00625                         Z->DenominatorPulsationsCount = 0;
00626                 else
00627                 {
00628                         Z->DenominatorPulsationsCount = 1;
00629                         Z->DenominatorPulsations = new double[Z->DenominatorPulsationsCount];
00630                         Z->DenominatorPulsations[0] = 1 / (Z->A * C2);
00631                 }
00632         }
00633 
00634         // R1 = 0 => Z1 = 1/sC1
00635         else if (cbValuesR1m->ItemIndex == 0)
00636         {
00637                 Z->NumeratorPulsationsCount = 0;
00638 
00639                 // XC2 = +oo
00640                 if (cbValuesC2m->ItemIndex == 0)
00641                         c = C1;
00642                 else
00643                 {
00644                         c = C1 + C2;
00645                 }
00646 
00647                 // R2 = +oo
00648                 if (cbValuesR2m->ItemIndex == cbValuesR2m->Items->Count - 1)
00649                 {
00650                         Z->A = 1 / c;
00651                         Z->b = -1;
00652                         Z->DenominatorPulsationsCount = 0;
00653                 }
00654                 else
00655                 {
00656                         Z->A = R2;
00657                         Z->b = 0;
00658                         Z->DenominatorPulsationsCount = 1;
00659                         Z->DenominatorPulsations = new double[Z->DenominatorPulsationsCount];
00660                         Z->DenominatorPulsations[0] = 1 / (R2 * c);
00661                 }
00662         }
00663 
00664         // Z1 = R1 + 1/sC1
00665         else
00666         {
00667                 // XC2 = +oo
00668                 if (cbValuesC2m->ItemIndex == 0)
00669                 {
00670                         // R2 = +oo => Z = Z1
00671                         if (cbValuesR2m->ItemIndex == cbValuesR2m->Items->Count - 1)
00672                         {
00673                                 Z->A = 1 / C1;
00674                                 Z->b = -1;
00675                                 Z->NumeratorPulsationsCount = 1;
00676                                 Z->NumeratorPulsations = new double[Z->NumeratorPulsationsCount];
00677                                 Z->NumeratorPulsations[0] = 1 / (R1 * C1);
00678                                 Z->DenominatorPulsationsCount = 0;
00679                         }
00680 
00681                         // Z = Z1 || R2
00682                         else
00683                         {
00684                                 Z->A = R2;
00685                                 Z->b = 0;
00686                                 Z->NumeratorPulsationsCount = 1;
00687                                 Z->NumeratorPulsations = new double[Z->NumeratorPulsationsCount];
00688                                 Z->NumeratorPulsations[0] = 1 / (R1 * C1);
00689                                 Z->DenominatorPulsationsCount = 1;
00690                                 Z->DenominatorPulsations = new double[Z->DenominatorPulsationsCount];
00691                                 Z->DenominatorPulsations[0] = 1 / ((R1 + R2) * C1);
00692                         }
00693                 }
00694 
00695                 // R1, C1 & C2 exist
00696                 else
00697                 {
00698                         // R2 = +oo
00699                         if (cbValuesR2m->ItemIndex == cbValuesR2m->Items->Count - 1)
00700                         {
00701                                 Z->A = 1 / (C1 + C2);
00702                                 Z->b = -1;
00703                                 Z->NumeratorPulsationsCount = 1;
00704                                 Z->NumeratorPulsations = new double[Z->NumeratorPulsationsCount];
00705                                 Z->NumeratorPulsations[0] = 1 / (R1 * C1);
00706                                 Z->DenominatorPulsationsCount = 1;
00707                                 Z->DenominatorPulsations = new double[Z->DenominatorPulsationsCount];
00708                                 Z->DenominatorPulsations[0] = (1 / C1 + 1 / C2) / R1;
00709                         }
00710 
00711                         // all Rs and Cs exist
00712                         else
00713                         {
00714                                 a = R1 * R2 * C1 * C2;
00715                                 b = R1 * C1 + R2 * (C1 + C2);
00716                                 d = sqrt(b * b - 4 * a);
00717                                 Z->A = R2;
00718                                 Z->b = 0;
00719                                 Z->NumeratorPulsationsCount = 1;
00720                                 Z->NumeratorPulsations = new double[Z->NumeratorPulsationsCount];
00721                                 Z->NumeratorPulsations[0] = 1 / (R1 * C1);
00722                                 Z->DenominatorPulsationsCount = 2;
00723                                 Z->DenominatorPulsations = new double[Z->DenominatorPulsationsCount];
00724                                 Z->DenominatorPulsations[0] = - (-b - d) / (2 * a);
00725                                 Z->DenominatorPulsations[1] = - (-b + d) / (2 * a);
00726                         }
00727                 }
00728         }
00729 
00730         return true;
00731 }
00732 //---------------------------------------------------------------------------
00733 
00734 void __fastcall TfmMain::UpdateTransferFunction(void)
00735 {
00736         unsigned int i;
00737 
00738         miExport->Enabled = H->OK = Z1->OK && Z2->OK;
00739         if (!H->OK) return;
00740 
00741         if (H->NumeratorPulsationsCount)
00742                 delete[] H->NumeratorPulsations;
00743         if (H->DenominatorPulsationsCount)
00744                 delete[] H->DenominatorPulsations;
00745 
00746         // H(s) = - Z2(s) / Z1(s)
00747         H->NumeratorPulsationsCount = Z2->NumeratorPulsationsCount + Z1->DenominatorPulsationsCount;
00748         H->DenominatorPulsationsCount = Z2->DenominatorPulsationsCount + Z1->NumeratorPulsationsCount;
00749         if (H->NumeratorPulsationsCount)
00750                 H->NumeratorPulsations = new double[H->NumeratorPulsationsCount];
00751         if (H->DenominatorPulsationsCount)
00752                 H->DenominatorPulsations = new double[H->DenominatorPulsationsCount];
00753         for (i = 0; i < Z2->NumeratorPulsationsCount; ++i)
00754                 H->NumeratorPulsations[i] = Z2->NumeratorPulsations[i];
00755         for (i = 0; i < Z1->DenominatorPulsationsCount; ++i)
00756                 H->NumeratorPulsations[i + Z2->NumeratorPulsationsCount] = Z1->DenominatorPulsations[i];
00757         for (i = 0; i < Z2->DenominatorPulsationsCount; ++i)
00758                 H->DenominatorPulsations[i] = Z2->DenominatorPulsations[i];
00759         for (i = 0; i < Z1->NumeratorPulsationsCount; ++i)
00760                 H->DenominatorPulsations[i + Z2->DenominatorPulsationsCount] = Z1->NumeratorPulsations[i];
00761         H->A = - Z2->A / Z1->A;
00762         H->b = Z2->b - Z1->b;
00763 }
00764 //---------------------------------------------------------------------------
00765 
00766 void __fastcall TfmMain::udScaleXMinChangingEx(TObject *Sender,
00767       bool &AllowChange, short NewValue, TUpDownDirection Direction)
00768 {
00769         AllowChange = false;
00770         if (NewValue < 0 && PlotArea->ScaleX->Min > MIN_FREQUENCY)
00771                 --PlotArea->ScaleX->Min;
00772         if (NewValue > 0 && PlotArea->ScaleX->Min + 1 < PlotArea->ScaleX->Max)
00773                 ++PlotArea->ScaleX->Min;
00774         RecalcPlots();
00775         pbGraph->Repaint();
00776         pbScaleX->Repaint();
00777         pbScaleY->Repaint();
00778 }
00779 //---------------------------------------------------------------------------
00780 
00781 void __fastcall TfmMain::udScaleXMaxChangingEx(TObject *Sender,
00782       bool &AllowChange, short NewValue, TUpDownDirection Direction)
00783 {
00784         AllowChange = false;
00785         if (NewValue < 0 && PlotArea->ScaleX->Min + 1 < PlotArea->ScaleX->Max)
00786                 --PlotArea->ScaleX->Max;
00787         if (NewValue > 0 && PlotArea->ScaleX->Max < MAX_FREQUENCY)
00788                 ++PlotArea->ScaleX->Max;
00789         RecalcPlots();
00790         pbGraph->Repaint();
00791         pbScaleX->Repaint();
00792         pbScaleY->Repaint();
00793 }
00794 //---------------------------------------------------------------------------
00795 
00796 void __fastcall TfmMain::RecalcPlots(void)
00797 {
00798         unsigned int i;
00799         double step, min, max;
00800 
00801         if (!H->OK) return;
00802 
00803         delete[] CorrectedBodePlot->X;
00804         delete[] CorrectedBodePlot->Y;
00805 
00806         CorrectedBodePlot->PointsCount = pbGraph->Width;
00807         CorrectedBodePlot->X = new double[CorrectedBodePlot->PointsCount];
00808         CorrectedBodePlot->Y = new double[CorrectedBodePlot->PointsCount];
00809 
00810         step = (PlotArea->ScaleX->Max - PlotArea->ScaleX->Min) / ((double)CorrectedBodePlot->PointsCount - 1);
00811         for (i = 0; i < CorrectedBodePlot->PointsCount; ++i)
00812         {
00813                 CorrectedBodePlot->X[i] = pow(10, PlotArea->ScaleX->Min + i * step) * 2 * M_PI;
00814         }
00815 
00816         UncorrectedBodePlot->PointsCount = H->NumeratorPulsationsCount + H->DenominatorPulsationsCount + 2;
00817         UncorrectedBodePlot->X = new double[UncorrectedBodePlot->PointsCount];
00818         UncorrectedBodePlot->Y = new double[UncorrectedBodePlot->PointsCount];
00819 
00820         for (i = 0; i < H->NumeratorPulsationsCount; ++i)
00821         {
00822                 UncorrectedBodePlot->X[i] = H->NumeratorPulsations[i];
00823         }
00824         for (i = 0; i < H->DenominatorPulsationsCount; ++i)
00825         {
00826                 UncorrectedBodePlot->X[i + H->NumeratorPulsationsCount] = H->DenominatorPulsations[i];
00827         }
00828 
00829         i = H->NumeratorPulsationsCount + H->DenominatorPulsationsCount;
00830 
00831         UncorrectedBodePlot->X[i++] = pow10(PlotArea->ScaleX->Min) * 2 * M_PI;
00832         UncorrectedBodePlot->X[i++] = pow10(PlotArea->ScaleX->Max) * 2 * M_PI;
00833 
00834         merge_sort(UncorrectedBodePlot->X, 0, i - 1);
00835 
00836         CalcCorrectedBodePlot(CorrectedBodePlot->PointsCount, CorrectedBodePlot->X, CorrectedBodePlot->Y);
00837         CalcUncorrectedBodePlot(UncorrectedBodePlot->PointsCount, UncorrectedBodePlot->X, UncorrectedBodePlot->Y);
00838 
00839         min = max = CorrectedBodePlot->Y[0];
00840         for (i = 1; i < CorrectedBodePlot->PointsCount; ++i)
00841         {
00842                 if (CorrectedBodePlot->Y[i] < min)
00843                         min = CorrectedBodePlot->Y[i];
00844                 else if (CorrectedBodePlot->Y[i] > max)
00845                         max = CorrectedBodePlot->Y[i];
00846         }
00847         for (i = 1; i < UncorrectedBodePlot->PointsCount; ++i)
00848                 if ((UncorrectedBodePlot->X[i] >= 2 * M_PI * pow10(PlotArea->ScaleX->Min)) && (UncorrectedBodePlot->X[i] <= 2 * M_PI * pow10(PlotArea->ScaleX->Max)))
00849                 {
00850                         if (UncorrectedBodePlot->Y[i] < min)
00851                                 min = UncorrectedBodePlot->Y[i];
00852                         else if (UncorrectedBodePlot->Y[i] > max)
00853                                 max = UncorrectedBodePlot->Y[i];
00854                 }
00855 
00856         PlotArea->ScaleY->Max = (int) ceil(max / 10) * 10;
00857         PlotArea->ScaleY->Min = (int) floor(min / 10) * 10;
00858         if (PlotArea->ScaleY->Max - PlotArea->ScaleY->Min < 20)
00859         {
00860                 PlotArea->ScaleY->Max = (int) ceil((max + 5) / 10) * 10;
00861                 PlotArea->ScaleY->Min = (int) floor((min - 5) / 10) * 10;
00862         }
00863 }
00864 //---------------------------------------------------------------------------
00865 
00866 void __fastcall TfmMain::pbScaleXPaint(TObject *Sender)
00867 {
00868         TCanvas *Canv;
00869         int w, h, i, j, x, th, decadesCount, decadeStep;
00870         double decadeWidth;
00871 
00872         w = pbScaleX->Width;
00873         h = pbScaleX->Height;
00874         Canv = pbScaleX->Canvas;
00875         decadesCount = PlotArea->ScaleX->Max - PlotArea->ScaleX->Min;
00876         decadeWidth = ((double)w - 1) / (double)decadesCount;
00877         for (decadeStep = 1; decadeStep * decadeWidth <= 100 || decadesCount % decadeStep; ++decadeStep);
00878 
00879         Canv->Font->Assign(Font);
00880         th = Canv->TextHeight('1');
00881 
00882         Canv->MoveTo(0, 0);
00883         Canv->LineTo(0, h - th - 2);
00884         Canv->TextOutA(0, h - th - 1, FrequenciesTxt[PlotArea->ScaleX->Min - MIN_FREQUENCY]);
00885         for (i = 1; i * decadeStep < decadesCount; ++i)
00886         {
00887                 x = round(i * decadeStep * decadeWidth);
00888                 Canv->MoveTo(x, 0);
00889                 Canv->LineTo(x, h - th - 2);
00890                 Canv->TextOutA(x - Canv->TextWidth(FrequenciesTxt[PlotArea->ScaleX->Min - MIN_FREQUENCY + i * decadeStep]) / 2, h - th - 1, FrequenciesTxt[PlotArea->ScaleX->Min - MIN_FREQUENCY + i * decadeStep]);
00891         }
00892         Canv->MoveTo(w - 1, 0);
00893         Canv->LineTo(w - 1, h - th - 2);
00894         Canv->TextOutA(w - Canv->TextWidth(FrequenciesTxt[PlotArea->ScaleX->Max - MIN_FREQUENCY]), h - th - 1, FrequenciesTxt[PlotArea->ScaleX->Max - MIN_FREQUENCY]);
00895 
00896         if (decadeStep != 1)
00897                 for (i = 1; i < decadesCount; ++i)
00898                         if (i % decadeStep)
00899                         {
00900                                 x = round(i * decadeWidth);
00901                                 Canv->MoveTo(x, 0);
00902                                 Canv->LineTo(x, (h - th - 2) * .7);
00903                         }
00904         if (decadeStep < 3)
00905                 for (i = 0; i < decadesCount; ++i)
00906                         for (j = 2; j < 10; ++j)
00907                         {
00908                                 x = round((i + log10l(j)) * decadeWidth);
00909                                 Canv->MoveTo(x, 0);
00910                                 Canv->LineTo(x, (h - th - 2) * .4);
00911                         }
00912 }
00913 //---------------------------------------------------------------------------
00914 void __fastcall TfmMain::FormResize(TObject *Sender)
00915 {
00916         if (pbScaleX->Width != (int)CorrectedBodePlot->PointsCount)
00917         {
00918                 RecalcPlots();
00919                 pbScaleY->Repaint();
00920         }
00921 }
00922 //---------------------------------------------------------------------------
00923 
00924 void __fastcall TfmMain::pbGraphPaint(TObject *Sender)
00925 {
00926         unsigned int i;
00927         int h, w, mx, my;
00928         TCanvas *Canv;
00929 
00930         Canv = pbGraph->Canvas;
00931         h = pbGraph->Height - 1;
00932         w = pbGraph->Width;
00933         mx = PlotArea->ScaleX->Max - PlotArea->ScaleX->Min;
00934         my = PlotArea->ScaleY->Max - PlotArea->ScaleY->Min;
00935 
00936         if (!H->OK)
00937         {
00938                 Canv->TextOut((pbGraph->Width - Canv->TextWidth("Układ niepoprawny")) / 2, (h - Canv->TextHeight("1")) / 2, "Układ niepoprawny");
00939                 return;
00940         }
00941 
00942         Canv->Pen->Color = clGray;
00943         Canv->MoveTo(round((log10l(UncorrectedBodePlot->X[0] / (2 * M_PI)) - (double) PlotArea->ScaleX->Min) * ((double)w - 1) / (double)mx), round(h * (PlotArea->ScaleY->Max - UncorrectedBodePlot->Y[0]) / my));
00944         for (i = 1; i < UncorrectedBodePlot->PointsCount; ++i)
00945                 Canv->LineTo(round((log10l(UncorrectedBodePlot->X[i] / (2 * M_PI)) - (double) PlotArea->ScaleX->Min) * ((double)w - 1) / (double)mx), round(h * (PlotArea->ScaleY->Max - UncorrectedBodePlot->Y[i]) / my));
00946         Canv->Pen->Color = clBlack;
00947         Canv->MoveTo(0, round(h * (PlotArea->ScaleY->Max - CorrectedBodePlot->Y[0]) / my));
00948         for (i = 1; i < CorrectedBodePlot->PointsCount; ++i)
00949                 Canv->LineTo(i, round(h * (PlotArea->ScaleY->Max - CorrectedBodePlot->Y[i]) / my));
00950 }
00951 //---------------------------------------------------------------------------
00952 
00953 void __fastcall TfmMain::pbScaleYPaint(TObject *Sender)
00954 {
00955         TCanvas *Canv;
00956         int i, w, h, ty, y, unitStep, unitsCount;
00957         double unitHeight;
00958 
00959         if (!H->OK) return;
00960 
00961         w = pbScaleY->Width;
00962         h = pbScaleY->Height;
00963         Canv = pbScaleY->Canvas;
00964         unitsCount = (PlotArea->ScaleY->Max - PlotArea->ScaleY->Min) / 10;
00965         unitHeight = (h - 1) / ((double)unitsCount);
00966         for (unitStep = 1; unitStep * unitHeight <= 50 || unitsCount % unitStep; ++unitStep);
00967 
00968         Canv->Font->Assign(Font);
00969         ty = Canv->TextHeight('1') / 2;
00970 
00971         Canv->MoveTo(Canv->TextWidth(IntToStr(PlotArea->ScaleY->Max)) + 1, 0);
00972         Canv->LineTo(w - 1, 0);
00973         Canv->TextOutA(0, 0, IntToStr(PlotArea->ScaleY->Max));
00974         for (i = 1; i * unitStep < unitsCount; ++i)
00975         {
00976                 y = round(i * unitStep * unitHeight);
00977                 Canv->MoveTo(Canv->TextWidth(IntToStr(PlotArea->ScaleY->Max - 10 * i * unitStep)) + 1, y);
00978                 Canv->LineTo(w - 1, y);
00979                 Canv->TextOutA(0, y - ty, IntToStr(PlotArea->ScaleY->Max - 10 * i * unitStep));
00980         }
00981         Canv->MoveTo(Canv->TextWidth(IntToStr(PlotArea->ScaleY->Min)) + 1, h - 1);
00982         Canv->LineTo(w - 1, h - 1);
00983         Canv->TextOutA(0, h - 1 - ty * 2, IntToStr(PlotArea->ScaleY->Min));
00984 
00985         if (unitStep != 1)
00986                 for (i = 1; i < unitsCount; ++i)
00987                         if (i % unitStep)
00988                         {
00989                                 y = round(i * unitHeight);
00990                                 Canv->MoveTo(w * .7, y);
00991                                 Canv->LineTo(w - 1, y);
00992                         }
00993 }
00994 //---------------------------------------------------------------------------
00995 
00996 
00997 void __fastcall TfmMain::miExportClick(TObject *Sender)
00998 {
00999         TStringList *Text;
01000 
01001         if (!sdExport->Execute()) return;
01002 
01003         Text = new TStringList;
01004 
01005         Text->Add("Uklad ze wzmacniaczem operacyjnym");
01006         Text->Add("");
01007 
01008         if (!AnsiCompareStr(static_cast<TComponent *>(Sender)->Name, "miExportuA741"))
01009         {
01010                 Text->Add("* CONNECTIONS:   NON-INVERTING INPUT");
01011                 Text->Add("*                | INVERTING INPUT");
01012                 Text->Add("*                | | POSITIVE POWER SUPPLY");
01013                 Text->Add("*                | | | NEGATIVE POWER SUPPLY");
01014                 Text->Add("*                | | | | OUTPUT");
01015                 Text->Add("*                | | | | |");
01016                 Text->Add(".SUBCKT UA741    1 2 3 4 5");
01017                 Text->Add("*");
01018                 Text->Add("  C1   11 12 8.661E-12");
01019                 Text->Add("  C2    6  7 30.00E-12");
01020                 Text->Add("  DC    5 53 DX");
01021                 Text->Add("  DE   54  5 DX");
01022                 Text->Add("  DLP  90 91 DX");
01023                 Text->Add("  DLN  92 90 DX");
01024                 Text->Add("  DP    4  3 DX");
01025                 Text->Add("  EGND 99  0 POLY(2) (3,0) (4,0) 0 .5 .5");
01026                 Text->Add("  FB    7 99 POLY(5) VB VC VE VLP VLN 0 10.61E6 -10E6 10E6 10E6 -10E6");
01027                 Text->Add("  GA    6  0 11 12 188.5E-6");
01028                 Text->Add("  GCM   0  6 10 99 5.961E-9");
01029                 Text->Add("  IEE  10  4 DC 15.16E-6");
01030                 Text->Add("  HLIM 90  0 VLIM 1K");
01031                 Text->Add("  Q1   11  2 13 QX");
01032                 Text->Add("  Q2   12  1 14 QX");
01033                 Text->Add("  R2    6  9 100.0E3");
01034                 Text->Add("  RC1   3 11 5.305E3");
01035                 Text->Add("  RC2   3 12 5.305E3");
01036                 Text->Add("  RE1  13 10 1.836E3");
01037                 Text->Add("  RE2  14 10 1.836E3");
01038                 Text->Add("  REE  10 99 13.19E6");
01039                 Text->Add("  RO1   8  5 50");
01040                 Text->Add("  RO2   7 99 100");
01041                 Text->Add("  RP    3  4 18.16E3");
01042                 Text->Add("  VB    9  0 DC 0");
01043                 Text->Add("  VC    3 53 DC 1");
01044                 Text->Add("  VE   54  4 DC 1");
01045                 Text->Add("  VLIM  7  8 DC 0");
01046                 Text->Add("  VLP  91  0 DC 40");
01047                 Text->Add("  VLN   0 92 DC 40");
01048                 Text->Add(".MODEL DX D(IS=800.0E-18 RS=1)");
01049                 Text->Add(".MODEL QX NPN(IS=800.0E-18 BF=93.75)");
01050                 Text->Add(".ENDS");
01051                 Text->Add("XUA741 0 2 4 5 3 UA741");
01052                 Text->Add("VCCPOS 4 0 DC 15");
01053                 Text->Add("VCCNEG 5 0 DC -15");
01054         }
01055         else
01056         {
01057                 Text->Add("* CONNECTIONS: NON-INVERTING INPUT");
01058                 Text->Add("*              | INVERTING INPUT");
01059                 Text->Add("*              | | OUTPUT");
01060                 Text->Add("*              | | |");
01061                 Text->Add(".SUBCKT OA     1 2 3");
01062                 Text->Add("*");
01063                 Text->Add("  RIN 1 2 1E9");
01064                 Text->Add("  EOUT 3 0 1 2 1E6");
01065                 Text->Add(".ENDS");
01066                 Text->Add("XOA 0 2 3 OA");
01067         }
01068 
01069         if ((cbValuesR11m->ItemIndex != 0) && (cbValuesR11m->ItemIndex != cbValuesR11m->Items->Count - 1))
01070                 if ((cbValuesC11m->ItemIndex != 0) && (cbValuesC11m->ItemIndex != cbValuesC11m->Items->Count - 1))
01071                 {
01072                         Text->Add("R11 1.5 1 " + IntToStr((int)(ValuesRm[cbValuesR11m->ItemIndex - 1])) + "." + IntToStr(round(ValuesRm[cbValuesR11m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesReVal[cbValuesR11e->ItemIndex]));
01073                         Text->Add("C11 2 1.5 " + IntToStr((int)(ValuesCm[cbValuesC11m->ItemIndex - 1])) + "." + IntToStr(round(ValuesCm[cbValuesC11m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesCeVal[cbValuesC11e->ItemIndex]));
01074                 }
01075         if ((cbValuesR11m->ItemIndex != 0) && (cbValuesR11m->ItemIndex != cbValuesR11m->Items->Count - 1))
01076                 if (cbValuesC11m->ItemIndex == cbValuesC11m->Items->Count - 1)
01077                         Text->Add("R11 2 1 " + IntToStr((int)(ValuesRm[cbValuesR11m->ItemIndex - 1])) + "." + IntToStr(round(ValuesRm[cbValuesR11m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesReVal[cbValuesR11e->ItemIndex]));
01078         if (cbValuesR11m->ItemIndex == 0)
01079                 if ((cbValuesC11m->ItemIndex != 0) && (cbValuesC11m->ItemIndex != cbValuesC11m->Items->Count - 1))
01080                         Text->Add("C11 2 1 " + IntToStr((int)(ValuesCm[cbValuesC11m->ItemIndex - 1])) + "." + IntToStr(round(ValuesCm[cbValuesC11m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesCeVal[cbValuesC11e->ItemIndex]));
01081         if ((cbValuesR12m->ItemIndex != 0) && (cbValuesR12m->ItemIndex != cbValuesR12m->Items->Count - 1))
01082                 Text->Add("R12 2 1 " + IntToStr((int)(ValuesRm[cbValuesR12m->ItemIndex - 1])) + "." + IntToStr(round(ValuesRm[cbValuesR12m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesReVal[cbValuesR12e->ItemIndex]));
01083         if ((cbValuesC12m->ItemIndex != 0) && (cbValuesC12m->ItemIndex != cbValuesC12m->Items->Count - 1))
01084                 Text->Add("C12 2 1 " + IntToStr((int)(ValuesCm[cbValuesC12m->ItemIndex - 1])) + "." + IntToStr(round(ValuesCm[cbValuesC12m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesCeVal[cbValuesC12e->ItemIndex]));
01085 
01086         if ((cbValuesR21m->ItemIndex != 0) && (cbValuesR21m->ItemIndex != cbValuesR21m->Items->Count - 1))
01087                 if ((cbValuesC21m->ItemIndex != 0) && (cbValuesC21m->ItemIndex != cbValuesC21m->Items->Count - 1))
01088                 {
01089                         Text->Add("R21 2.5 2 " + IntToStr((int)(ValuesRm[cbValuesR21m->ItemIndex - 1])) + "." + IntToStr(round(ValuesRm[cbValuesR21m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesReVal[cbValuesR21e->ItemIndex]));
01090                         Text->Add("C21 3 2.5 " + IntToStr((int)(ValuesCm[cbValuesC21m->ItemIndex - 1])) + "." + IntToStr(round(ValuesCm[cbValuesC21m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesCeVal[cbValuesC21e->ItemIndex]));
01091                 }
01092         if ((cbValuesR21m->ItemIndex != 0) && (cbValuesR21m->ItemIndex != cbValuesR21m->Items->Count - 1))
01093                 if (cbValuesC21m->ItemIndex == cbValuesC21m->Items->Count - 1)
01094                         Text->Add("R21 3 2 " + IntToStr((int)(ValuesRm[cbValuesR21m->ItemIndex - 1])) + "." + IntToStr(round(ValuesRm[cbValuesR21m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesReVal[cbValuesR21e->ItemIndex]));
01095         if (cbValuesR21m->ItemIndex == 0)
01096                 if ((cbValuesC21m->ItemIndex != 0) && (cbValuesC21m->ItemIndex != cbValuesC21m->Items->Count - 1))
01097                         Text->Add("C21 3 2 " + IntToStr((int)(ValuesCm[cbValuesC21m->ItemIndex - 1])) + "." + IntToStr(round(ValuesCm[cbValuesC21m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesCeVal[cbValuesC21e->ItemIndex]));
01098         if ((cbValuesR22m->ItemIndex != 0) && (cbValuesR22m->ItemIndex != cbValuesR22m->Items->Count - 1))
01099                 Text->Add("R22 3 2 " + IntToStr((int)(ValuesRm[cbValuesR22m->ItemIndex - 1])) + "." + IntToStr(round(ValuesRm[cbValuesR22m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesReVal[cbValuesR22e->ItemIndex]));
01100         if ((cbValuesC22m->ItemIndex != 0) && (cbValuesC22m->ItemIndex != cbValuesC22m->Items->Count - 1))
01101                 Text->Add("C22 3 2 " + IntToStr((int)(ValuesCm[cbValuesC22m->ItemIndex - 1])) + "." + IntToStr(round(ValuesCm[cbValuesC22m->ItemIndex - 1]*10))[2] + "e" + IntToStr(ValuesCeVal[cbValuesC22e->ItemIndex]));
01102 
01103         Text->Add("VIN 1 0 AC 1");
01104         Text->Add(".AC DEC 100 1e" + IntToStr(PlotArea->ScaleX->Min) + " 1e" + IntToStr(PlotArea->ScaleX->Max));
01105         Text->Add(".PROBE V(3)");
01106         
01107         Text->SaveToFile(sdExport->FileName);
01108 
01109         delete Text;
01110 }
01111 //---------------------------------------------------------------------------
01112 
01113 void __fastcall TfmMain::miAboutClick(TObject *Sender)
01114 {
01115         Application->MessageBoxA("OpAmpSim - Operational amplifier simulator - symulator prostych układów ze wzmacniaczem operacyjnym.\n\n"
01116         "Copyright (C) 2006\nPiotr 'GhosT' Wydrych\nKrzystof Rusek\nGrzegorz Gancarczyk\n\n"
01117         "Program wykonany na przedmiot Układy Elektroniczne na kierunku Elektronika i Telekomunikacja na WEAIiE AGH.\n\nProgram jest tylko skromną pomocą naukową. Nie może zastąpić rozważań i obliczeń teoretycznych oraz symulacji w programach specjalistycznych (np. PSpice).\n\n"
01118         "http://opampsim.sf.net/\nhttp://sf.net/projects/opampsim/\n\n"
01119         "This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nTekst licencji: http://www.gnu.org/licenses/gpl.txt", "About...", MB_OK | MB_ICONINFORMATION);
01120 }
01121 //---------------------------------------------------------------------------
01122 

Generated on Mon Sep 11 03:40:29 2006 for OpAmpSim by doxygen 1.3.6