Escolar Documentos
Profissional Documentos
Cultura Documentos
pour le partiel de TP :
savez vous :
créer un projet ? De quels fichiers il est constitué ? Quel est le processeur utilisé ? Quel
fichier doit être impérativement situé dans votre répertoire de travail ?
http://www.analog.com/processors/testdrive
RAPPEL DE PRINCIPE:
Le travail demandé est normalement explicitement indiqué, sur fond rose: ne considérez
donc pas comme « à faire » les explications qui vous permettront de réaliser le travail
demandé dans un second temps.
Si aucune erreur n’a été trouvée une nouvelle fenêtre est ouverte sur la droite, nommée
Disassembly, montrant les instructions dans la mémoire PM avec les adresses (en vert).
Une flèche jaune indique l’instruction prête à être exécutée : début du programme à
l’adresse 0x90100.
Dans la fenêtre de l’éditeur la même flèche et un rond rouge sont apparus, indiquant aussi
l’instruction prête à être exécutée.
Tous les tests réalisés dans les langages évolués : IF, FOR, WHILE... sont
réalisés avec des tests sur ces bits.
Relance du programme :
Pour relancer le programme il faut replacer le compteur PC sur la première instruction, il
est plus prudent de refaire un chargement du programme par F7.
Puis F5 pour le lancement.
Ouvrir les fenêtres permettant d’observer les registres de données et la zone des
variables. Recharger (F7) et exécuter le programme en mode pas à pas. Noter et
comprendre l’évolution des contenus des variables en mémoire (a,b,x) et des registres (r0
à r3).
/**********************************************************************
tpx_x.asm c’est-à-dire des commentaires sur votre projet
***********************************************************************/
.GLOBAL _main;
.section/dm seg_dmda;
// placer ici les variables nécessaires
.SECTION/PM seg_pmco;
_main:
// placer ici le code de votre programme (entre _main : et rts ; )
RTS ;
_main.end:
Constitution du projet:
Deux fichiers qu’il faut toujours ajouter :
ADSP-21369-EZKIT.LDF à placer dans linker file
21369_IVT.asm à ajouter aux sources files
Lorsque votre fichier source est terminé (code et variables) le compilateur peut traduire
en hexadécimal les instructions mais il ne sait pas à quelles adresses de la mémoire les
placer.
Le fichier ADSP-21369-EZKIT.LDF lui indique comment placer les différentes sections
repérées dans le fichier source ( seg_data, seg_code...).
Ce fichier dépend de l'architecture du système, c'est-à-dire, aussi, du DSP utilisé.
Un emplacement pertinent pour ce fichier dans le projet est le sous répertoire Linker file
(clic droit, add file).
travail demandé :
réserver dans la mémoire DM la place pour 3 variables, val_a0 , val_a1 et val_a2
Le programme à écrire récupère les valeurs depuis la mémoire DM les placent dans les
registres r0 et r1, fait l’addition et place le résultat en mémoire .
Faire ainsi l’addition de 0x12345678 avec 0x23456789 (il faut attribuer ces valeurs au
variables lors de leurs déclarations)
Visualisez ces données dans la mémoire DM:
Memory two column
Les variables ont étés, conformément au fichier .ldf utilisé, placées à partir de l’adresse
0xB8000
. Lancer le programme.
Celui-ci est sans fin: la grande boucle (deb) se répète indéfiniment.
Il est toujours possible de l'arrêter avec shift-F5
Observer alors (memory/two columns/ « souris droit »/go to/ browse/somme) le contenu
de la variable somme.
. Placer un point d'arrêt sur l'instruction r0=r0+1; relancer plusieurs fois, observer et
expliquer l'évolution de r0 et de somme
. Enlever le point d’arrêt et placez en un sur l'instruction jump deb qui se trouve à la fin
du programme.
Observer et expliquer l'évolution de r0 et de somme
Mettre des commentaires dans votre programme pour expliquer ce que chaque instruction
réalise et faites les vérifier par un enseignant.
Sur la carte le circuit AD1835 permet de faire des conversions analogique vers numérique
et numérique vers analogique :
AD1835 :
15 registres pour configurer le circuit, dont 13 programmables, de 10 bits, et 2 en lecture
seule de 6 bits (détection des valeurs crêtes)
CAN et CNA au format 24 bits, échantillonnage programmé ici à 48KHz par voie, bande
passante de 20 à 20KHz (bande audio), niveau max de sortie 2.8V.
initSPORT.asm pour initialiser la liaison série utilisée pour les échanges avec le
circuit CAN/CNA
initPLL_SDRAM
Seuls les fichiers en gras et soulignés seront modifiés, pour obtenir le traitement désiré.
Utilisation :
USB
alimentation
Sortie
5 cinchs stéréo: une casque
entrée, 4 sorties
remarques :
le fichier passetout.asm contient la fonction _main et le sous programme d'interruption,
it_reception_sport0, seul ce sous programme est à modifier pour réaliser les différents
filtres obtenus par équation de récurrence dans les exercices suivants.
La fonction d'interruption gère l'alternance entre les deux voies (gauche et droite) il faut
donc écrire 2 fois le code en utilisant des variables propres à chacune des voies si les
entrées ou les sorties précédentes sont utilisées dans l'équation.
2. Filtre passe-bas:
on considère l'équation suivante qui définit un filtre passe bas du premier ordre:
S k =a G 0 E k +b S k−1 (1)
2 π Fc Fe
avec: a= et b=
F E+2 π F c F E +2 π F c
Fe
en considérant K= :
Fc
2π K
a= et b=
K +2 π K +2π
inversement si on part d'une équation de la forme s(k)= A e(k) + B s(k-1)
on peut calculer le gain en continu: G = A/(1-B) et le rapport obtenu Fe/Fc= B/(1-B)
Informations utiles:
. pour les nombres fractionnaires il faut les faire suivre de « r », par exemple: r0=0.124r;
. calcul de s(k)
programmation:
Modifier le fichier passetout et l'enregistrer sous un autre nom
Prendre en compte la fréquence d'échantillonnage de 48KHz pour faire les calculs et écrire
le programme pour obtenir une fréquence de coupure de 500Hz.
Le programme principal est le même que pour le filtre passe-tout: initialisation des
différents éléments: les fichiers nécessaires sont les mêmes que ceux du filtre passe-tout.
utiliser une case mémoire de nom sortiea (et éventuellement sortieb pour la
voie b), par exemple, pour mémoriser s(k) qui sera s(k-1) à la prochaine
interruption .
Mesurer le gain (dB) à 30Hz , 500Hz et 2KHz. Conclure sur la nature du filtre.
Mesurer le gain (dB) à 1KHz et 10 KHz. Conclure sur l'ordre du filtre.
Faire un relevé en fréquence /dB de 20Hz à 20KHz.
Passe haut:
s( p) τ . p
=
e( p) 1+τ . p
−1
en utilisant p → 1−Z on obtient
Te
1 1
s( p)= 2 2 . e( p) avec τ =ω p =j. ω
ζ .τ . p+1)
( τ ∗p +2∗ n
( 1−z(−1))
p→
en appliquant Te
s(k) étant la sortie actuelle et s(k-1) et s(k-2) les sorties aux instants d'échantillonnages
précédents.
τ =a= F E
En prenant et 2.ζ=b
Te 2.π .F C
on obtient:
(2) e( k)−s( k −2) . a 2+s( k −1).( 2.a 2+a.b)
s( k) =
1+a 2+a.b
afin de n'avoir que des coefficients inférieurs à 1 (fractionnaires 1.31) on les divisent tous
par 2.
il faudra bien sur multiplier le résultat obtenu par 2 en utilisant un décalage à gauche.
Par exemple: r0 = ashift r0 by 1;
il faut ici utiliser ashift, et non pas lshift, car il est important de conserver le bit de signe.
Ashift : décalage arithmétique qui ne modifie pas le bir de signe
lshift : décalage logique, aucune protection du bit ded signe
Travail demandé:
voie_a:
r0=dm(sortiea); //sk-1
r1=dm(sortiea2); // sk-2
r2=0.007135r;
r3=0.90939r;
r4=0.416529r;
r5=r10*r2(ssf); //
r6=r0*r3(ssf); //
r5=r5+r6;
r6=r1*r4(ssf); //
r5=r5-r6;
r5=ashift r5 by 1; //
dm(sortiea2)=r0; //
dm(sortiea)=r5; //
r10=lshift r5 by -8; //
jump fin;
voie_b:
r0=dm(sortieb);
r1=dm(sortieb2);
r2=0.007135r;
r3=0.90939r;
r4=0.416529r;
r5=r10*r2;
r6=r0*r3;
r5=r5+r6;
r6=r1*r4;
r5=r5-r6;
r5=ashift r5 by 1;
dm(sortieb2)=r0;
dm(sortieb)=r5;
r10=lshift r5 by -8;
fin:
dm(TXSP1A)=r10; // DAC1
dm(TXSP1B)=r10; // DAC2
dm(TXSP2A)=r10; // DAC3
dm(TXSP2B)=r10; // DAC4
tester ce programme et placer des commentaires aux emplacements repérés par \\.
1. Produit de convolution:
on peut définir un système par sa réponse impulsionnelle (à un dirac):
schéma:
système
dirac Rimp
t' t1
est donnée par l'intégrale du produit des deux signaux de t' à t1
En effet ici de 0 à t' le produit est nul, donc l'intégrale aussi, il suffit d'intégrer
de t1 à t'...
Initialisations:
les registres suivants sont utilisés:
I0 pour le signal voie A (L0 =L_IMP)
I1 pour le signal voie B (L1 =L_IMP)
I2 pour la réponse impulsionnelle (L2=L_IMP)
(par défaut une réponse impulsionnelle est ici créée, tout à fait artificielle)
.var rep_impul[L_IMP]={0.9r,0.8r,0.7r,0.6r,0.5r,0.4r,0.3r,0.2r,0.1r};
Convolution:
partie du programme qui est à comprendre mais que vous n'aurez par la suite
qu'à utiliser telle quelle, si vous respectez bien les déclarations et les
initialisations définies ci dessus (sur fond magenta).
Graphiquement:
Mémoire réponse
impulsionnelle
sortie
convolution
Mémoire signal
entrée
signal
Lecture du passé I0
REP_IMPUL
I2
comme on utilise les deux voies de la stéréo I1 est utilisé pour la seconde voie
à la place de I0.
il faut créer un projet qui doit contenir tous les fichiers utilisés dans le TP
précédent :
21369_IVT.asm
initSRU.asm
convol_exemple.asm
initSPORT.asm
init1835viaSPI.asm
initpllsdram.dsp
ADSP-21369-EZKIT.LDF
observer rapidement le signal de sortie pour une entrée sinusoïdale de 20Hz à
20KHz de valeur 0.4V crête à crête
conclure sur la nature du filtre.
Méthode de travail:
créer des réponses impulsionnelles en plaçant les valeurs dans le tableau de la
réponse impulsionnelle il faut penser à actualiser la valeur de L_IM
relever sur la même feuille échelle log de 20Hz à 20KHz
en prenant comme échelle de -50dB à +20 dB
conseils de mesure : l'averaging ne permet pas de voir le vrai signal, il ne faut
donc pas l'utiliser à priori, cependant lorsque le signal est noyé dans le bruit il
faut l'utiliser pour faire une mesure d'amplitude plus précise
Réponse impulsionnelle 2:
Réponse impulsionnelle 3:
les valeurs :
0,9 0 0 0,9
Ve(max)= 1Vcàc
Réponse impulsionnelle 4 :
les valeurs :
0,9 0 0 0 0 0 0 0 -0,9
Ve(max)= 1.5Vcàc
Réponse impulsionnelle 5:
les valeurs:
0,9 0,6 0,4 0,2 -0,9 -0,6 -0,3 -0,2 +0,1
20*log(abs(0.9+0.6*exp(-2*pi*i*x/48000)+0.4*exp(-4*pi*i*x/48000)+0.2*exp(-
6*pi*i*x/48000)-0.9*exp(-8*pi*i*x/48000)-0.6*exp(-10*pi*i*x/48000)-0.3*exp(-
12*pi*i*x/48000)-0.2*exp(-14*pi*i*x/48000)+0,1*exp(-16*pi*i*x/48000)))
Générateur de signal.
Pour générer un signal avec le kit « il suffit » de placer les valeurs successives
de ce signal sur la sortie du KIT.
Si ce signal est périodique on peut calculer à chaque fois une nouvelle valeur
en fonction de la précédente mais il est aussi possible de lire circulairement
un tableau de valeurs placé dans la mémoire de données (DM).
Il faut faire des envois de valeurs vers le CODEC à espaces réguliers, on utilise
ici les interruptions mises en place précédemment même si on n'utilise pas ici
les valeurs envoyées par le CODEC:
lire le contenu du buffer de réception (valeur non utilisée mais cette
lecture est obligatoire pour le bon fonctionnement)
écrire la valeur à transmettre dans les 4 buffers de transmission
Les initialisations sont les mêmes que précédemment afin d'obtenir les
interruptions au rythme de 48000/s par voie:
call _initPLL; // Initialise la PLL: fréquence du coeur CCLK
call _initSDRAM; // Initialise SDRAM (SDCLK)
call _initSRU; // Initialise SRU, broches DAI/DPI pour le kit
call _initSPORT; // Initialise les liaisons séries utilisées sur le kit
call _init1835viaSPI; // Initialise le codec
LIRPTL = SP0IMSK; // valide l'interruption sur le port série de réception des
données de réception
pour réaliser les différents aiguillages nécessaires il est possible d'utiliser des
instructions conditionnelles, et plus particulièrement des sauts conditionnels:
IF cdt instruction;
cdt pouvant être notamment:
eq si résultat de l'instruction précédente nul
ne si résultat non nul
le si résultat négatif ou nul (lt : strictement négatif)
gt si résultat strictement positif (ge : positif ou nul)
en pratique instruction est un jump etiquette
un algorithme qui utilise ce type de test (qui s'approche des instructions du
DSP) est :
lire sens et le comparer à 0
si sens ==0 saut à moins (si le résultat de l'addition est 0)
(par exemple :
r1=dm(sens) ;
r2=0;
r1=r1+r2; //le résultat est nul si sens =0
if eq jump diminuer ;// on saute
// ici il faut donc augmenter)
sinon on augmente :
val = val + pas
envoi de val
si val < 0.4r saut à fin
(par exemple : r1=dm(val) ; r2=0.9r;r1=r1-r2 ; if le jump fin;)
1.DELAYS :
Le delay est un effet souvent utilisé avec les instruments de musique électrique (claviers et
guitares essentiellement), il ajoute au signal le signal retardé.
L'effet delay des musiciens utilise des temps de retard allant de quelques dizaines de
millisecondes à plusieurs secondes. Les retards de 10 à 200ms ne produisent pas une
répétition du son décelable mais modifie la sonorité.
Pour obtenir un delay très audible (ce qui est notre but ici, donc plutôt un écho) il faut avoir
un temps le plus grand possible, il faut donc mémoriser une longue série de valeurs.
Pour ce projet, afin de disposer de plus de mémoire DM il faut utiliser les fichiers du
répertoire « delay » du serveur :
ADSP-21369-EZKIT_mem_ext.LDF au lieu du .LDF habituel
pour_projet_mem_ext.asm comme fichier de base pour le programme
Écrire le programme et tester avec ces différentes valeurs. Le retard pourra être utilisé sur une
seule des voies afin de pouvoir comparer avec le signal d'origine.
L'interruption obtenue par action sur BP1 permet de repositionner l'index sur le
buffer.
2. Tremolo :
Pour cela on module en amplitude le signal avec un triangle 0.01 à 0.99. On ne crée pas en
mémoire un signal triangulaire mais on fait évoluer un coefficient dans l'interruption en
appelant la fonction triangle.
a. fonction triangle :
cette fonction utilise les variables suivantes en entrées :
valmax= 0.99
valmin =0.01
pas = 0.00001 à 0.00005 pour tester
sens
val (=0.5 au début)
et modifie éventuellement les variables suivantes (sorties) :
val (coefficient de modulation)
sens
A chaque interruption de réception la valeur transmise est celle de la valeur reçue à laquelle on
applique le coefficient contenu dans la variable val avant de l'envoyer vers les sorties.
3. Stereo move :
le but est d'obtenir un signal tournant entre les 2 voies.
Il faut deux zone mémoire , une pour mémoriser les entrées de voiea et une pour celles de
voieb.
Mais le calcul de la sortie de chaque voie prend en compte les entrées des 2 voies (valeur
précédente de l'autre voie).
On peut, si on ne veut pas utiliser les index des zones mémoires, créer 2 variables va et vb qui
sont mises à jour à chaque réception d'une nouvelle valeur.
3. Flanger
chaque voie est traitée 48000 fois par seconde, en arrondissant à 50000, cela représente un
temps de 20us entre 2 interruptions, c'est-à-dire entre 2 valeurs dans la zone mémoire
des valeurs passées de l'entrée.
Ce type d'effet ajoute au signal direct le signal retardé, mais le retard varie dans le temps.
Le temps du retard est de l'ordre de 1 à 10ms.
Le retard utilisé varie lui même en un temps de l'ordre de 1 seconde à une dizaine de
secondes.
Il faut donc :
prévoir 1 zone mémoire de 500 cases 'entree' (ce qui peut permettre d'avoir un retard
maximum d'environ 10ms)), pour mémoriser les signaux d'entrées d'une des entrées (la
seconde entrée sera envoyée sans modifications pour faire des comparaisons)
(le décalage devant évoluer dans le temps on utilise également l'interruption de
réception série afin de modifier ce retard.)
prévoir une zone mémoire pour les valeurs du retard, qui peut donc aller de 50 à 500 à
50, donc 900 valeurs.
le programme principal doit, lors de l'initialisation, écrire dans la mémoire 'retard' les
différentes valeur du retard (c'est-à-dire les valeurs 50 à 500 à 50).
si maxcptr>cptr :
lire une valeur dans la zone des retards
mettre cptr à 0
sinon :
incrémenter cptr
TP6
utilisation des timers en interruptions.
Registres:
TMxCTL contrôle
TMxCNT compteur, registre 32 bits, utilisé en interne par le système
TMxPRD période, registre 32 bits, 31 utilisés
TMxW largeur d'impulsion, 32 bits, 31 utilisés
Lorsqu’un timer est validé en mode PWM il génère sur sa sortie TIMERx un signal :
de période tp = tpclk * TMxPRD
de niveau actif th = tpclk * TMxW
pour valider l'interruption générée par le timer il faut écrire dans imask:
bit set imask P2I; // pour valider les interruptions TIMER0
sweep :
écrire un programme utilisant le générateur sinusoïdal du TP4 : le but est de faire varier le
pas (donc la fréquence) automatiquement : par un timer qui change le pas de lecture dans
la mémoire du signal avec un temps de cycle de 5s (par exemple). Pour que l'évolution ne
soit pas trop hachée il faut varier le pas de 1 à 500, si on change de 1 à chaque fois il faut
aller de 1 à 500 puis à 1 donc 999 valeurs que l'on peut placer par programme dans une
zone mémoire de DM.
Tremolo :
reprendre le trémolo du TP5. Le coefficient est modifié par l'interruption timer, on peut
commencer avec un cycle de 3s et 600 valeurs différentes.