Bonjour, je dois faire un NCO ( numerically controlled oscillator ) en c. Quelqu'un à t-il d'jà réalisé cela? Car je ne vois pas trop comment le faire. Je ne trouve d'algorithme!
Merci de votre aide.
Bonjour, je dois faire un NCO ( numerically controlled oscillator ) en c. Quelqu'un à t-il d'jà réalisé cela? Car je ne vois pas trop comment le faire. Je ne trouve d'algorithme!
Merci de votre aide.
- Avec un accumulateur dont la sortie est réduite modulo N.
L'accumulateur réalise l'opération acc = (acc+x)modulo(N). La fréquence est fixée par le nombre x placé à l'entrée de l'accumulateur et par le cadencement de l'accumulateur et on obtient en sortie acc qui est la phase (la valeur N correspondant à 2*pi) de l'oscillateur.
- La fréquence est donnée par Freq = x/N/T, T étant le temps entre deux accumulations.
- On peut réaliser un déphasage en initialisant l'accumulateur.
- Si on souhaite une sortie sinusoïdale, il suffit de calculer le sinus de la phase en sortie ou utiliser une table.
Quelle est le format des données de sortie ? Binaire, analogique ?Envoyé par sandball22
Pour binaire, c'est simple :
[unixoide]
Mais c'est sans garantie, car usleep() fait ce qu'il peut. Pour avoir de la précision, il faut utiliser un générateur matériel (timer) qui est fait pour ça, et qu'il suffit de programmer correctement. C'est pour quelle plateforme ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 void oscillator(double frequence_hz) { /* demi-periode en micro-secondes : HPus = 1E6 / (2 x Fhz) */ unsigne long half_period_us = 5E5 / frequence_hz; for (;;) { output(1); usleep(half_period_us); output(0); usleep(half_period_us); } }
Les formats en entrées et en sortie doivent etre en binaire.
x doit être sur 24bits. Je dois utilser une table. La sortie de cette table sera sur 16bits. Avez-vous déjà réalisé ceci en c?
J'ia trouvé un programme en C++ mais je ne le comprend pas trop. Je ne sais pas si cela fait bien ce qu'à décrit diogene.
.h
.cpp
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 namespace SPUC { /*! \brief NCO with 32 bit accumulator \ingroup pll */ //!: //! Numerically controlled oscillator (with 32 bits accumulator) //! returns the top (mask_bits) MSBs from accumulator //! Useful for carrier recovery where top bits used for input to //! sine,cos lookup table. //! FCW : frequency control word //! ACC : accumulator //! Frequency must be set through interface routines set_frequency //! or reset_frequency. //! Load routine is to allow frequency to be updated (typically with //! a loop filter). //! When not changing frequency call "clock" routine. class nco { public: unsigned long phase; // char v[20]; protected: unsigned long acc; unsigned long fcw; unsigned long new_fcw; unsigned long mask_bits; public: //! Constructor nco(long bits=8); //! Reset object inline void reset() { phase = new_fcw = fcw = acc = 0; } //! Set frequency control word inline void set_frequency(unsigned long freq) { fcw = freq; } //! Set frequency control word and register for frequency control word inline void reset_frequency(unsigned long freq) { new_fcw = fcw = freq; } //! Return current phase inline long get_phase(void) { return(phase);} //! Load new frequency control word inline void load(long loop_filter_out) {new_fcw = fcw + loop_filter_out;} //! Clock NCO with new frequency control word input long clock(long loop_filter_out); //! Clock NCO without changing frequency control word long clock(); }; } // namespace SPUC #endif
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 // Set nco.h for description. #include <spuc.h> #include <nco.h> namespace SPUC { nco::nco(long bits) { acc = fcw = new_fcw = phase = 0; mask_bits = MASK_NEG_HI(bits); } long nco::clock() { acc += new_fcw; phase = acc & mask_bits; // truncate return(phase); } long nco::clock(long loop_filter_out) { new_fcw = fcw + loop_filter_out; return(clock()); } } // namespace SPUC
Alors c'est du numérique (24-bit / 16-bit) et non du binaire ! (1-bit).Envoyé par sandball22
Je ne connais pas. Il y a des math là-dessous et je sens que ça ne va pas me plaire... Je connais mes limites...
Oui, c'est basé sur ce principe.Je ne sais pas si cela fait bien ce qu'à décrit diogene.
Pratiquement pas.Mais il manque du code non?réalise effectivement le NCO.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 long nco::clock() { acc += new_fcw; phase = acc & mask_bits; // truncate return(phase); }
Ce qui manque :
- la partie "lookup table" adressée à partir du retour de clock()
- le système de cadencement qui doit appeler clock() à intervalles réguliers
Mais cela dépend du détail du projet que tu veux réaliser.
L'entrée est codée sur 24 bits et en sortie de mes tables est codé sur 16bits
cf page 1
www.nova-eng.com/downloads/ip_digifrec.pdf
Quel est en fait la nature de ton projet ?
Es-tu censé écrire en C un programme faisant la même chose que ce circuit ?
Je dois transcrire en c le Nco (page 3). Il n'y a pas besoin de retranscrire exactement comme sur le schéma, mais le même principe.
Alors, il ne te manque pas plus que signalé à la réponse #8 si tu n'a pas à programmer le changement de fréquence.
Ou sont les tables? je comprend pas comment ces fichiers peuvent fonctionner.
Tu crées au départ une table contenant les sinus que tu adresses à partir de la phase. En gardant les notations utilisées avant, ca donne qq chose du genreOu sont les tables? je comprend pas comment ces fichiers peuvent fonctionner.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 int Sinus[256]; .... for (i=0; i<256; i++) Sinus = 32767*sin(2*M_PI/256*i); .... Sortie = Sinus[clock()];
Alors commence par transcrire l'équivalent de long nco::clock() en C. On reviendra ensuite sur le problème de la table
Si je ne m'occupe pas des tables, il suffit juste de re transcrire
en c?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 long nco::clock() { acc += new_fcw; phase = acc & mask_bits; // truncate return(phase); }
sandball22 : Oui, commençons par là
J'ai réalisé le NCO mais voila ce que j'obtiens en sortie (cf piece jointe).
Est-ce convenable?
Partager