This block realizes the temporal response of a Voltage Controled Oscillator defined with this expression:
This block is a Discrete Basic Block(DBB) and the integral of the instaneous phase is computed with the trapezoidal method.
The period of event input port, which must be in accord to the 'Step' parameters, is the discrete integration time step.
This block contains two discrete frequency dividers, with one which is able to be dynamically computed.
The event output port(s) is(are) the zero crossing date of the output wave form.
Full possibilities of this block are described in the following 'Super Block equivalent Model' section.
(cf See Also section for futher details)
If set 1
If set 1
/* vco Scicos VCO with frequency divider Event block * Type 4 simulation function ver 1.1 - scilab-3.0 * 1 decembre 2003 - IRCOM GROUP - Author : A.Layec * 10 janvier 2005 : rajout option du rapport de division dynamique * passage type 4 * remplace otutes les anciennes routines vco */ /* REVISION HISTORY : * $Log$ */ #include "machine.h" #include <math.h> #include <stdio.h> #include "scicos_block.h" /* Calcul la forme temporelle de sortie d'un VCO et ses instants de transitions * produit un évènement en sortie toutes les N fois (N:rapport de division) * * entrées régulières : u1[0] : u3(t) tension de commande * u2[0] : valeur du rapport de division * * sorties régulières : y[0] : ys(t)=cos(wot+phi(t)) * avec phi(t)=integral(Kv*u3(t))dt pour le cas linéaire * phi(t)=intégral(gain*tanh(coef*u3(t)))dt pour le cas non-linéaire * * entrées évènementielles : Tstep pas de résolution * * sorties évènementielles : evout[0] : Instant de passage aux valeurs rpar[3]*(ipar[0]+u1[0]) * * paramètres réels : rpar[0] : pas d'intégration * rpar[1] : wo pulsation libre de l'oscillateur * rpar[2] : kv sensibilité * rpar[3] : instant de transition * si ipar[1]==1 : * rpar[4] : gain de la fonction non-linéaire * rpar[5] : coeffficient de la fonction non-linéaire * rpar[6] : moyenne du bruit sur la commande * rpar[7] : variance du bruit sur la commande * * paramètres entiers : ipar[0] : réalise une détection dynamique * 0 : passage aux valeurs rpar[1] * 1 : passage aux valeurs rpar[1]*u2[0] * ipar[1] : réalise la fonction non-linéaire en entrée du VCO * 0 : linéaire * 1 : alpha*tanh(beta*u1[0]) * ipar[2] : réalise un deuxième diviseur de fréquence à rapport entier * 0 : pas de sencond diviseur * sinon valeur du 2eme rapport * ipar[3] : type de bruit * 0 : pas de bruit * 1 : bruit normal sur la commande d'entrée * * état discret : z[0] : valeur de la phase instantannée * z[1] : valeur de l'entrée à l'état précédent * z[2] : valeur de l'angle instantannée * z[3] : valeur de 'angle à l'état précédent * z[4] : compteur incremental de l'angle (ex: ..+2*%pi*N[k-1]+2*%pi*N[k]+..) * z[5] : valeur de la distance à parcourir jusqu'à la prochaine transition (ex : 2*%pi*N) * z[6] : compteur incremental de l'angle du 2eme diviseur (ex: ..+2*%pi*N[k-1]+2*%pi*N[k]+..) */ /*prototype*/ void vco(scicos_block *block,int flag) { /*déclaration des variables*/ double *y; double *u1; double *u2; double step; /*pas d'intégration*/ double wo; /*pulsation libre*/ double kv; /*sensibilité*/ double v; /*valeur de passage*/ double t; /*valeur du temps de simulation*/ double f_u; /*valeur de l'entrée(avec sa fonction)*/ double alpha; /*gain de la fonc non-linéaire*/ double beta; /*coef de la func non-linéaire*/ /*Récupération des adresses des ports réguliers*/ y=(double *)block->outptr[0]; u1=(double *)block->inptr[0]; u2=(double *)block->inptr[1]; step=block->rpar[0]; wo=block->rpar[1]; kv=block->rpar[2]; v=block->rpar[3]; /* Le flag 1 calcule l'intégrale discrète (trapèze) de la tension d'entrée * calcul de l'angle instantannée theta(t)=(wot+phi(t)) * Place le cos(theta(t)) dans y[] */ if(flag==1) { /*Calcul de la fonction d'entrée*/ if (block->ipar[1]!=0) { alpha=block->rpar[4]; beta=block->rpar[5]; f_u=alpha*tanh(beta*u1[0]); } else f_u=u1[0]; /*multiplication par sensibilité linéaire*/ f_u=kv*f_u; if (block->ipar[3]==1) /*Test si bruit*/ { /*déclaration*/ double phi_n; int i,k; /*Appel noiseblk_c*/ noiseblk_c((i=1,&i),(k=1,&k),&block->rpar[7],&block->rpar[6],&phi_n); /*rajout bruit*/ f_u=f_u+(phi_n); } /*Calcul de la phase instantannée : intégrale de la valeur d'entrée par la méthode des trapèzes*/ block->z[0]=(step/2)*(f_u+block->z[1])+block->z[0]; /*Mise en mémoire de f_u*/ block->z[1]=f_u; /*Calcul de l'angle wo*t+phi(t)*/ t=get_scicos_time(); /*récupération de la valeur du temps*/ block->z[2]=t*wo+block->z[0]; /*Calcul du cos(wo*t+phi(t))*/ y[0]=cos(block->z[2]); } /* Le flag 3 détermine l'instant de passage de theta(t) à rpar[3]*ipar[0]->z[5] * par une méthode d'extrapolation et place le résultat dans tvec[0] */ else if(flag==3) { if (block->ipar[0]==1) { /*déclaration*/ double *u2; /*récupération adresse*/ u2=(double *)block->inptr[1]; /*fprintf(stderr,"U2[0]=%f\n",u2[0]);*/ block->z[5]=v*u2[0]; } else block->z[5]=v; /*block->z[5]=v*block->ipar[0];*/ /*Teste si la valeur de transistion est dépassée*/ if((block->z[2]-block->z[4])>=block->z[5]) { /*Calcul de l'instant de transition*/ block->evout[0]=(((block->z[4]+block->z[5])-block->z[3])*step)/(block->z[2]-block->z[3]); /*Incrément valeur z[4]*/ block->z[4]=block->z[4]+block->z[5]; } /*Test si il existe un deuxième port de sortie evènenemtiel*/ /*fprintf(stderr,"nevout=%d\n",block->nevout);*/ if(block->ipar[2]!=0) { if((block->z[2]-block->z[6])>=v*block->ipar[2]) { /*Calcul de l'instant de transition*/ block->evout[1]=(((block->z[6]+v*block->ipar[2])-block->z[3])*step)/(block->z[2]-block->z[3]); /*Incrément valeur z[6]*/ block->z[6]=block->z[6]+v*block->ipar[2]; } } } /*Le flag 2 mémorise la valeur de thetha_k-1 dans z[3]*/ else if(flag==2) { /*Mise en mémoire de*/ block->z[3]=block->z[2]; } }