Université de Savoie Module I621 Travaux Pratiques Architecture des Ordinateurs Sylvain MONTAGNY [email protected] Bâtiment chablais, bureau 13 04 79 75 86 86 TP1 : Simulation des mémoires caches et du pipeline d’un processeur TP 2 : Application sur cible à microprocesseurs (1) TP 3 : Application sur cible à microprocesseurs (2) Retrouver tous les documents nécessaires au TP sur le site www.master-electronique.com Université de Savoie Module I621 Architecture des Ordinateurs TP1 Simulation de mémoire cache et pipeline Objectifs : Comprendre le déroulement d’un logiciel dans une architecture à microprocesseur. Un compte rendu sera remis avec pour consignes : Format PDF en un seul fichier. Le nom du fichier sera : I621-TPx-Nombinome1-Nombinome2.pdf Envoyé à [email protected] Votre compte rendu sera bien reçu seulement si vous avez un message de confirmation de notre part. Les parties recopiées entres binômes ne seront pas corrigées. 1. Présentation 1.1. Objectifs Nous allons travailler sur une architecture MIPS 32 bits (Microprocessor without Interlocked Pipeline Stages). L'architecture MIPS est une architecture de processeur de type RISC (Reduced Instruction Set Computer). Son architecture est une référence. Les processeurs fabriqués selon cette architecture sont surtout utilisés dans les systèmes embarqués. L’objectif n’est pas d’étudier cette architecture en particulier, ni d’étudier le jeu d’instruction de ce processeur. Néanmoins nous allons examiner le déroulement d’un logiciel à l’aide d’un simulateur d’architecture MIPS32. Ceci nous permettra de mieux comprendre l’organisation et l’exécution du code pour le microprocesseur. Vous pouvez parcourir le site web www.mips.com, pour visualiser quelques applications des microprocesseurs MIPS. 1.2. Présentation du simulateur MARS “MARS is a software simulator for the MIPS assembly language intended for educational use. We will explore the capabilities of MARS release 3.2.1. MARS may be downloaded from www.cs.missouristate.edu/MARS.“ 2. Prise en main de l’environnement Remarques : Certaines questions relèvent plus de la culture générale. Vous pourrez à juste titre chercher des informations sur Internet à ce sujet. >Lancer Mars.jar, dont l’application est codée en JAVA. >Ouvrir le code assembleur “row-major.asm” >Assembler le code (Run>Assemble) L’icone permet de lancer l’exécution du programme jusqu’à la fin. En utilisant cette fonction vous observez le surlignement jaune qui montre l’adresse du programme en cours d’exécution. Les valeurs du programme qui sont calculées apparaissent dans le segment de donnée. L’icone permet de faire un reset du programme et des valeurs de l’ensemble des registres du simulateur. L’icone permet d’exécuter une instruction après l’autre. Autrement dit, de faire de l’exécution pas à pas. Cette fonction est complété par l’icône , qui permet de revenir d’un pas : “single-step backwards”. Le processeur utilise un adressage par octet. Vous pouvez changer le format de visualisation du contenu des adresses et des adresses en hexadécimal ou en décimal : . Dans le logiciel MARS, ajuster le « run speed » : de voir l’évolution de l’algorithme en fonction du temps. afin d’avoir le temps Dans la présentation du “segment de code” (Text segment en anglais) vous avez les colonnes suivantes : Q1. Précisez ce que chacune des colonnes contiennent. Vous prendrez un exemple en étudiant la ligne de code 41 du programme. Vous vous aiderez de la documentation en annexe. Tout doit pouvoir être justifié : loop: mult $s0, $t1 Q2. Quel est le registre du microprocesseur qui spécifie l’adresse de la prochaine instruction à exécuter dans le logiciel. Quelle est la valeur de ce registre au Reset? Est-ce logique par rapport à l’implantation de votre programme en mémoire ? Q3. Qu’est ce que le « text segment » et le « data segment » ? Q4. Expliquez les cases : dans le « data segment ». Q5. Sachant que le processeur MIPS32 est un processeur 32 bits, quel est la taille d’un mot mémoire ? Quelle quantité d’information le processeur sera-t-il capable de stocker en un seul cycle ? Depuis l’aide, (Help>Help>Basic_Instructions) vous trouverez l’ensemble des instructions disponibles dans ce microprocesseur. Les processeurs MIPS et leurs architectures ont beaucoup évolués depuis leur première version. Le document ci-dessous présente une introduction du jeu d’instruction de ce processeur. Q6. Qu’est ce que le jeu d’instruction d’un processeur ? Q7. Expliquer en une phrase le message que souhaite faire passer le constructeur au sujet du jeu d’instruction de l’ensemble des processeurs MIPS. (Ceci est aussi vrai pour tous les processeurs et beaucoup d’autres technologies). Q8. Expliquer ce que fait le programme en regardant le code C dans les commentaires (au début du code assembleur). Essayer de retrouver les différentes étapes depuis le code assembleur. Dans le code suivant, vous écrirez sans rentrer dans le détail, le code C aligné sur le code assembleur. CODE ASSEMBLEUR .data data: .word 0 : 256 # storage for 16x16 matrix of words .text li $t0, 16 # $t0 = number of rows li $t1, 16 # $t1 = number of columns move $s0, $zero # $s0 = row counter move $s1, $zero # $s1 = column counter move $t2, $zero # $t2 = the value to be stored loop: mult $s0, $t1 # $s2 = row * #cols (two-instruction sequence) mflo $s2 # move multiply result from lo register to $s2 add $s2, $s2, $s1 # $s2 += column counter sll $s2, $s2, 2 # $s2 *= 4 (shift left 2 bits) for byte offset CODE C sw addi $t2, data($s2) # store the value in matrix element $t2, $t2, 1 # increment value to be stored # Loop control: addi $s1, $s1, 1 # increment column counter bne $s1, $t1, loop # not at end of row so loop back move $s1, $zero # reset column counter addi $s0, $s0, 1 # increment row counter bne $s0, $t0, loop # not at end of matrix so loop back # We're finished traversing the matrix. li $v0, 10 # system service 10 is exit syscall # we are outta here. 3. Applications 3.1. Statistique d’exécution Dans le processeur MIPS comme dans tous les processeurs, il existe des instructions : De calcul arithmétique et logique De transfert de donnée (µP>Mémoire ou Mémoire>µP) Instruction de contrôle (saut ou branchement conditionnel) Q9. Grâce à l’outil « Instruction Statistics », donner le pourcentage des instructions les plus utilisées. Selon vous, d’un point de vue de la rapidité d’exécution, quel type d’instruction le processeur sait bien exécuter ? Pour lesquelles il est le plus lent, pourquoi ? Note : cliquer sur afin de lier l’outil au code que vous avez chargé. 3.2. Le pipeline Les processeurs MIPS intègrent un pipeline. Q10. Préciser l’intérêt des pipelines dans un microprocesseur d’après le document suivant présent dans la documentation du processeur MIPS Figure 1 : Fonctionnement sans mise en œuvre du pipeline Figure 2 : Fonctionnement avec mise en œuvre du pipeline Q11. Un des aléas possible du pipeline est en relation avec les branchements dans le programme. Dans le programme utilisé, donner la première instruction de saut conditionnel et expliquer la. Préciser aussi quelle solution avons-nous pour éviter cet aléa en particulier. 3.3. Solution des aléas du pipeline Un outil présent dans le simulateur est le BHT Simulator (Branch History Table Simulator). Cet outil est en fait la représentation d’une architecture présente dans les processeurs. Cette table permet d’enregistrer dans un espace de stockage le résultat des branchements conditionnels : Soit le branchement est pris (TAKEN) Soit le branchement est non pris (NOT TAKEN) Cette table n’a pas une taille infinie, et il arrive qu’il ne soit pas possible de renseigner tous les branchements présents dans un code. La taille de cette table est spécifier par le champ : « #of BHT entries ». >cliquer sur afin de lier le l’outil au code que vous avez chargé. Q12. Expliquer pourquoi l’historique de branchement peut permettre d’améliorer le déroulement du pipeline. Q13. A l’issu de l’exécution complète du code, combien de branchement ont causés une rupture du pipeline, et combien n’ont pas ralentit le déroulement du programme ? 3.4. Les mémoires caches 3.4.1 Etude de l’algorithme utilisé Q14. Expliquer en exécutant l’algorithme « row-major.asm », et en visualisant le segment de données, comment sont rangées les lignes et les colonnes du tableau en mémoire ? Note : Vous pouvez visualiser les valeurs en décimal plutôt qu’en hexadécimal pour que ce soit plus lisible. > Ouvrir l’outil « Memory Reference Visualisation ». Cet outil permet de représenter graphiquement l’espace mémoire du microprocesseur. Les valeurs par défaut sont configurées pour schématiser exactement le tableau data[16][16], c'est-à-dire un tableau de 16 lignes et 16 colonnes. A chaque fois qu’un accès mémoire est réalisé, la case concernée est colorée. Q15. Quelles remarques pouvez-vous faire sur les accès en mémoire en exécutant l’algorithme du code « row-major.asm » puis celui du code « column-major.asm » ? Column Major Algorithm Row Major Algorithm for (col = 0; col < 16; col++) for (row = 0; row < 16; row++) data[row][col] = value++; for ( row = 0; row < 16; row++) for ( col = 0; col < 16; col++) data[row][col] = value++; 3.4.2 Performance des algorithmes à l’aide des mémoires caches Les processeurs MIPS32 possèdent des mémoires caches. Nous allons effectuer différents tests afin de mettre en évidence l’intérêt des mémoires caches dans une architecture à microprocesseurs. Notamment, nous allons utiliser les deux algorithmes « columsmajor.asm » et « row-major.asm ». > Ouvrir le Data Cache Simulator, et connecter le à votre code . Q16. Dans cet outil donner le nom des deux types de cache que nous avons vu en cours et préciser rapidement le fonctionnement de chacune d’elle. Q17. Expliquer les deux politiques de remplacement : LRU et Random. Pour quel type de cache cela est valable. Q18. Comment est calculé le «cache size » ? Dans la configuration par défaut on a : Placement policy : Direct Mapping Number of block : 8 Cache block size : 4 Q19. Avec « row-major.asm » et en vous plaçant dans la configuration par défaut, expliquer en fonction du code en C qui s’exécute ce qu’il se passe. Justifier le taux de Hit et le taux de Miss. Q20. Quels sont les performances que vous pouvez prédire si la taille des blocs passe de 4 à 8 mots ? Vérifier ce résultat en simulation et expliquer pourquoi. Q21. Faites la même chose en passant de 4 à 2 mots, faite la même vérification en simulation. Note : Vous n’êtes pas obligé de fermer l’outil « mémoire cache » pour ouvrir et compiler un autre code. Q22. Reprenez les 3 dernières questions et faite la même chose avec l’algorithme « columnmajor.asm ». Donner les performances (taux de Hit et Miss) et expliquer pourquoi. Toujours avec l’algorithme « column-major.asm », afficher deux instances de l’outil mémoire cache, et faite une comparaison simultanée avec : Placement policy : Direct Mapping Number of block : 8 Cache block size : 4 Placement policy : Direct Mapping Number of block : 16 Cache block size : 16 Q23. A-t-on amélioré le taux de Hit ? Faite un essai avec la mémoire cache “full associative” : Placement policy : Direct Mapping Placement policy : Full Associative Number of block : 8 Number of block : 8 Cache block size : 4 Cache block size : 4 Q24. A-t-on amélioré le taux de Hit ? Q25. Pourquoi n’a-t-on pas de résultat très performant avec la mémoire cache associative pour ce programme en particulier. 4. Documentation Université de Savoie Module I621 TP 2 Programmation d’applications sur cible Le compte rendu de TP : Un compte rendu sera rendu à la fin de la séance avec pour consignes : Format PDF en un seul fichier. Le nom du fichier sera : I621-TPx-Nombinome1-Nombinome2.pdf. Envoyé par email à [email protected]. Votre compte rendu sera bien reçu seulement si vous avez un message de confirmation de ma part. I. Objectifs du TP Le but de ces manipulations est de découvrir un environnement de programmation moins habituel. Cela met en évidence certaines considération (espace mémoire limité, ressources limitée… etc) que vous avons habituellement peu l’habitude de prendre en compte. Le processeur cible est un processeur DSP (Digital Signal Processeur). Comme sont nom l’indique il est destiné à réaliser des applications de traitement du signal. C’est pour cette raison que nous application sera orienté vers un algorithme qui permettra de modifier certains paramètres d’un signal sonore. 1. Matériel à votre disposition Certains des éléments suivants sont présents sur votre plan de travail. Une carte Processeur DSK5416 Une paire d’enceinte amplifiée Un câble audio Un câble USB Un câble d’alimentation pour la carte 2. Montage du TP Nous réaliserons une application audio classique. Dans notre cas, l’objectif final est d’appliquer un filtre d’écho sur un fichier son. Le montage du TP est donné à la figure suivante. Cependant, il faut impérativement suivre scrupuleusement les instructions du paragraphe ‘Instruction pour la connexion de la carte’ pour éviter tout disfonctionnement. Attention : Il est important de relier la sortie du PC à LINE IN et les enceintes à SPKR OUT. 27/03/2013 Page 1/6 Switches USB LED LINE OUT Carte DSK C5416 PCM 3002 SPKR OUT 3. LINE IN Instruction pour la connexion de la carte Cette procédure est à réaliser avec attention chaque fois que pour une raison ou une autre la connexion USB ne fonctionne plus (Re)Brancher l’alimentation de la carte DSK. Attendre que les LEDs aient clignoté puis restent allumées Brancher le câble USB. Lancer CCS (Code Composer Studio) Se connecter à la cible : Debug > Connect Une icône verte doit apparaître en bas à gauche de la fenêtre de CCS pour préciser que la carte est bien connectée au PC. Remarque : L’allumage et l’extinction des enceintes près de la carte DSP font perdre la connexion USB dues à des perturbations électro-magnétique. Il faudra donc toujours laisser les hauts parleurs allumés lors des manipulations. II. Présentation de CCS : Ouvrir le projet template.pjt (Project>Open…>template.pjt) 1. Présentation générale CCS est un Logiciel dit IDE (Integrated Development Environment) pour compiler, assembler, linker et débuguer des programmes pour le DSK (DSP Starter Kit), autrement dit la carte de développement DSP. Ce logiciel est donc utilisé dans toutes les phases de développement d’une application : Coder, Compiler, assembler, et linker : Créer un projet, écrire le code en utilisant l’éditeur, compiler et éditer les liens. Débuguer : Vérification de l’algorithme, des affectations des variables. Utilisation de Break Points (point d’arrêt dans le programme), fonctionnement du programme en pas à pas, etc… 27/03/2013 Page 2/6 2. Analyse : Statistiques, analyse temps réelle, analyse temps réel, etc… Prise en main de CCS Vous allez prendre en main CCS en utilisant les différentes fonctionnalités à partir d’un programme simple. Dans le tutorial de CCS, on peut retrouver les définitions suivantes pour les fichiers contenus dans le projet. .pjt This file contains all of your project build and configuration options .lib This library provides runtime support for the target DSP chip .c This file contains source code that provides the main functionality of this project .h This file declares the buffer C-structure as well as define any required constants .asm This file contains assembly instructions .cmd This file maps sections to memory Remarque : le projet est de type DSP/BIOS. Cela offre l’avantage d’une configuration simplifié du système d’exploitation présent dans la mémoire interne du processeur. Par ailleurs cette interface de configuration DSP BIOS permet de prendre en main le noyau temps réel multitâches, dont nous n’utiliserons pas les caractéristiques ici. 3. Premier programme Le programme du DSP utilise le codec audio PCM3002 qui est en fait un convertisseur A/N & N/A. Le codec audio est vu comme un périphérique classique du point de vue du processeur. Ce programme recopie simplement le signal reçu sur l’entrée « Line In » vers la sortie « Spkr Out ». Compiler le projet en entier (Project > Rebuild All) et charger le code exécutable (.out) dans le DSP (File > Load Program). Lancer l’application (Debug > Run) et vérifier le fonctionnement. Pour cela vous utiliserez le fichier son mis à votre disposition pour le test. Q1. En positionnant un point d’arrêt dans le code (double clic en colonne de gauche), visualiser les échantillons right_input, right output, left_input et left output (clic droit sur la variable > Add to watch Window). Vérifier le fonctionnement correct du programme. III. Analyse et conception d’un programme 1. Fichier de commande et implantation du code en mémoire Le fichier de commande (dossier ‘Generated File’>‘templatecfg.cmd’) est généré automatiquement à partir du fichier de configuration template.cdb. De plus, si l’utilisateur souhaite le compléter il peut le faire dans un autre fichier qui sera joint au projet (fichier_xxx.cmd). Observer le fichier de commande templatecfg.cmd et notamment les parties MEMORY, puis SECTIONS. Q2. Expliquer à quoi sert un fichier de commande d’une façon générale, et à quoi servent précisément les parties MEMORY, puis SECTIONS ? 27/03/2013 Page 3/6 Le processus de compilation fournit un code assembleur spécifique à ce DSP. Ce langage assembleur utilise par exemple la directive .text pour désigner du code. Q3. D’après le contenu du fichier ‘templatecfg.cmd’ à quelle adresse sera implanté le code (.text) du projet compilé ? Vérifier et justifier votre réponse de deux façons : 2. En visualisant la mémoire programme (View>Memory) En visualisant le fichier template.map généré à la compilation Amplification du son A partir de ce projet, nous allons réaliser le traitement des échantillons audio reçus. Les fonctions suivantes font parties de la library dsk5416f.lib : unsigned int switch_status_display(void) Cette fonction retourne la valeur présente sur les switches présent sur la carte. Q4. En utilisant la fonction fonction switch_status_display () présente dans le fichier switches.c, réaliser un amplificateur des voies droites et gauches suivant la valeur des interrupteurs. Le prototype de la fonction sera le suivant : void amplification(Int16 in, Int16 *p_out, Int16 ampli). Int16 in : Echantillon d’entrée Int16 *p_out : Pointeur sur l’échantillon de sortie après traitement Int16 ampli : Coefficient multiplicateur pour l’amplification Note : Uint32 est un « Unsigned int sur 32 bits » Int16 est un « Signed int sur 16 bits » En passant la souris sur les types redéfinis (Uint32, Int16…. etc), et en cliquant sur le fichier concerné on peut avoir des informations complémentaires : Q5. D’après l’étude des différents « typedef » qui sont réalisés, expliquer l’intérêt de ces déclarations plutôt que les utilisations classique (short, int, long, double… etc) ? 3. Enregistrement du son et visualisation des échantillons. 3.1. Buffer linéaire On utilisera dans un premier temps un buffer linéaire avec décalage des échantillons précédents et insertion du premier échantillon en première case du tableau. Q6. Créer une nouvelle fonction réalisant le stockage des 128 derniers échantillons de la voie droite et de la voie gauche. Les buffers (tableaux) seront définis par les déclarations suivantes : 27/03/2013 Page 4/6 #define MAXBUFSIZE 128 // en début de fichier Int16 in_buffer_right[MAXBUFSIZE]; // déclaration en variable globale Int16 in_buffer_left[MAXBUFSIZE]; Et le prototype de la fonction sera le suivant : void linear_buffer( Int16 ech, Int16* buff); Int16 ech : échantillon à enregistrer Int16* buff : Pointeur sur le tableau d’échantillons Q7. CCS permet d’afficher des zones mémoires (ex : tableaux) sous forme de graphiques (View > Graph > Time/Frequency). Représenter le signal audio par un graphique en complétant convenablement les champs demandés. Note : En C, l’adresse d’un tableau en mémoire est son nom. 3.2. Buffer circulaire Le processus de capture par buffer linéaire défini précédemment est relativement couteux en nombre de cycles. Nous allons le remplacer par un buffer circulaire. Nous prendrons des buffers circulaires de taille MAXBUFSIZE=1024. Q8. Ecrire une nouvelle fonction permettant d'enregistrer un signal dans deux buffers circulaires (droite et gauche), avec le prototype suivant: void circular_buffer(Int16 ech, Int16* buff); Int16 ech : échantillon à enregistrer Int16* buff : Pointeur sur le tableau d’échantillons IV. Traitement numérique d’un signal sonore 1. Filtre d'écho On désire implémenter un filtre d'écho. C'est-à-dire que l’algorithme logiciel implémenté est une amplification d’un échantillon arrivé précédemment. Formule : y (n) x(n) G.x(n k ) y(n) est l’échantillon de sortie x(n) est l’échantillon de musique non traité à l’entrée de la carte (à la sortie du lecteur MP3) x(n-k) est l’échantillon stocké dans le buffer avec un retard de k échantillons. G le gain sur l’échantillon retardé. Q9. Quel est le lien entre le délai en secondes et le nombre d’échantillons sachant que la période d’échantillonnage (capture des échantillons sonore) est de 24 000 Hz ? Trouver alors la taille du tableau (MAXBUFFSIZE) que vous devez implémenter pour un retard de 0,2s. Q10. Réaliser à la fois l’enregistrement circulaire des échantillons (pour effectuer le retard) et le calcul qui implémente cet écho. On prendra G=1 (c'est-à-dire qu’on superposera à puissance égale l’écho et le signal original). 27/03/2013 Page 5/6 2. Utilisation de la mémoire Q11. Quel est le retard maximum que vous auriez pu réaliser ?. Faites tout d’abord un essai de façon pratique (en essayant des valeurs), puis vérifier en visualisant l’allocation mémoire faite par les buffers des deux voies (fichier .map). Q12. Quelle est le nom de la zone mémoire utilisée pour l’allocation de ces buffers ? On s’aperçoit qu’une fois de plus, dans un système embarqué, nous sommes limités en termes de ressources. Nous voyons très facilement ici les limitations dues à la taille de la mémoire centrale interne au composant. Une première façon pour contourner la limitation mémoire de la zone utilisée est de placer les données dans une zone plus grande. Visualiser le fichier template.cmd, qui est un fichier de commande. SECTIONS { .buffer > DARAM47 } Nous allons inclure le code suivant dans le fichier principale grâce à la directive #pragma. #pragma DATA_SECTION (in_buffer_right, ".buffer") #pragma DATA_SECTION (in_buffer_left, ".buffer") Q13. Expliquer l’action de l’éditeur de lien à la vue du fichier de commande template.cmd jumelé à l’ajout des lignes #pragma dans le code source. Vérifier son effet grâce à l’étude de l’implantation des buffers dans le fichier généré « .map ». Q14. Quelle est la nouvelle taille maximale des buffers (en échantillons et en secondes) ? Vous pouvez faire un nouvel essai de l’écho pour faire le plus grand écho possible. 3. Estimation de la charge processeur Le DSP utilisé possède un système d’exploitation temps réel multitâche non utilisée ici. Un Scheduler permet de faire le séquencement entre toutes les taches à exécutées dans le système. Nous avons dans notre cas qu’une tâche qui s’exécute Q15. Dans le cas de notre application, estimer la charge CPU ? Proposez une amélioration de votre système. 27/03/2013 Page 6/6 Université de Savoie Module I621 TP3 Programmation d’applications sur cible Le compte rendu de TP : Un compte rendu sera rendu à la fin de la séance avec pour consignes : Format PDF en un seul fichier. Le nom du fichier sera : I621-TPx-Nombinome1-Nombinome2.pdf. Envoyé par email à [email protected]. Votre compte rendu sera bien reçu seulement si vous avez un message de confirmation de ma part. I. Méthode classique de génération de sinus Dans premier temps nous allons générer des fréquences d’une façon classique. C'est-à-dire que la valeur du sinus sera calculée pour chaque échantillon. L’objectif sera de jouer une mélodie. Cette mélodie se trouve enregistrée sous forme d’un tableau de notes. Chaque ligne du tableau correspond aux caractéristiques de chacune des notes : fréquence, durée, amplitude. Fréquence (Hz) Durée (s) Amplitude (V) 200 480 650 0.3 0.6 0.45 2 2 2 1000 0.75 2 Note 1 Note 2 Note 3 …… …… …… Note n En langage C, chaque case du tableau se présente sous la forme d’une structure : struct Note { int freqNote; float dureeNote; float AmplitudeNote; }; # define TAILLE_MORCEAU_MUSIC 4 //Exemple de Morceau sur 4 notes => tableau de 4 notes struct Note Morceau_Music[TAILLE_MORCEAU_MUSIC]= {{440,0.25,2},{200,0.25,3},{880,0.25,1},{2000,0.25,4}}; 1. Préparation Le DSP fonctionne à fréquence d’échantillonnage fixe de 24 kHz que l’on notera F ech . Q1. Combien d’échantillon NB_ECH_PERIO sont contenu dans une période T note d’une note quelconque ? Dessiner votre signal échantillonné sech (t ) sur une période en plaçant T note et F ech . …………………………………………………………………………………………………... Q2. Donner l’expression de sech (t ) en fonction de k [0; NB _ ECH _ PERIO 1] , et de NB_ECH_PERIO. …………………………………………………………………………………………………... La période de retentissement de la note est simplement réalisé en connaissant le nombre d’échantillon total ( NB_ECH_DUREE ) qui sera envoyé au Codec Audio. Q3. Donner l’expression de NB_ECH_DUREE au cours d’une note de durée D note . …………………………………………………………………………………………………... 2. Réalisation sur le DSP Le nombre de bits du convertisseur analogique/numérique est de 16. Cela signifie que les valeurs des signaux en sortie du convertisseur prennent des valeurs [215 ;215 1] [32768;32767] Q4. Ecrire le code d’une fonction [ int Calcul_NB_ECH_PERIO(…,…) ] qui retourne le nombre d’échantillons contenus dans la période de la note ? Les arguments à passer à la fonction sont libres de choix. Ecrire le code d’une fonction [ int Calcul_NB_ECH_DUREE(…,…) ]qui Q5. retourne le nombre d’échantillons contenus dans la durée de la note ? Les arguments à passer à la fonction sont libres de choix. Ecrire le code qui permet de générer une note de fréquence 1000 Hz, de durée Q6. 5 secondes. Vous pouvez limiter l’amplitude du sinus pour avoir un son plus faible. Ecrire le code qui permet de générer le morceau de musique dont les notes Q7. sont données dans le tableau page suivante. Note : L’amplitude de tous les échantillons seront de 10000. Notes Morceau Note 1 – Si_3 Note 2 - Mi Note 3 - Sol Note 4 - Fa # Note 5 - Mi Note 6 – Si_4 Note 7 - La Note 8 – Fa # Note 9 - Mi Note 10 - Sol Note 11 – Fa # Note 12 – Ré # Note 13 - Fa Note 14 - Si Note 16 - Si Note 17 - Si Note 18 - Mi Note 19 - Sol Note 20 - Fa # Note 21 - Mi Note 22 – Si_4 Note 23 - Ré Note 24 – Ré bem Note 25 – Do Note 26 – La bem Note 27 – Do Note 28 - Si Note 29 - Si bem Note 30 - Si bem Note 31 - Sol Note 32 - Mi Note 33 - Mi Note 34 - Sol Fréquence (Hz) 494 659 784 740 659 988 880 740 659 784 740 622 698 494 494 494 659 784 740 659 988 1174 1108 1046 830 1046 988 932 932 784 659 659 784 Durée (s) 0.3 0.45 0.3 0.3 0.6 0.3 0.9 0.9 0.45 0.3 0.3 0.6 0.3 0.9 0.6 0.3 0.45 0.3 0.3 0.6 0.3 0.6 0.3 0.6 0.3 0.45 0.3 0.3 0.6 0.3 0.9 0.6 0.3 II. DDS : Direct Digital Frequency Une façon de modifier la fréquence du sinus est d’utiliser une structure DDS : Direct Digital Frequency. Cette structure est présentée à la figure suivante : Le registre « n » est une phase. A chaque cycle d’horloge de fréquence F ech , on ajoute au nombre précédemment stocké dans un accumulateur, un nombre n. Lorsque l’accumulateur arrive à saturation (dépassement des index du tableau de sinus), il reboucle et une nouvelle période d’accumulation est entamée. Ci-dessous, l’évolution de la phase (équivalente à l’index du tableau) pour une incrémentation de 1 à chaque coup d’horloge. La phase de votre sinus peut aussi être vue comme l’index de votre tableau de sinus. C'est-àdire que pour réaliser un sinus deux fois plus rapide, il suffit de lire une case sur deux du tableau de sinus. Pour un sinus trois fois plus rapide, une case sur trois… etc. Bien sûr, on ne peut pas lire plus d’échantillon que NB_ECH_PERIO (valeur constante qui a servi à l’initialisation du tableau de sinus). Donner l’expression du pas fréquentiel, c'est-à-dire la différence entre deux Q8. fréquences successives que nous pourrons obtenir en fonction de NB_ECH_PERIO et Fech. Faire l’application numérique avec NB_ECH_PERIO=48 et Fech=24kHz. Nous reprenons le tableau de la mélodie que nous devons générer. Quel pas fréquentiel faut-il respecter ? Donner la valeur de NB_ECH_PERIO Q9. de notre tableau de sinus pour que cette condition soit respectée. Q10. 3. Donner la fréquence max et min que nous allons pouvoir générer. Réalisation sur le DSP Q11. D’après le fichier de commande, quelle zone mémoire pourrait être capable de contenir l’ensemble de ces échantillons. Le programmeur doit donc savoir gérer l’emplacement de ces variables en mémoires. On se propose de placer votre tableau d’échantillon dans un emplacement mémoire plus large : celui que vous avez sélectionné. Cela est réalisé en 2 étapes très simples : On associe votre tableau d’échantillon à une directive : « .buffer » : #pragma DATA_SECTION (nom de votre tableau, ".buffer") On spécifie dans un nouveau fichier de commande .cmd (que vous rajouterez au projet) que la section compilée en .buffer sera placée dans votre emplacement choisi. Cela permet de faire passer l’information à l’éditeur de lien la nouvelle attribution des variables dans l’espace mémoire. On peut remarquer que templatecfg.cmd (le fichier de commande généré par l’outil de développement) est intégré au début du fichier afin de reprendre toutes les anciennes affectations et simplement de rajouter la nouvelle. templatecfg.cmd SECTIONS { .buffer > Nom de la section dans laquelle il faut mettre votre tableau } Q12. Réaliser une fonction qui initialise l’ensemble de votre tableau de sinus. Q13. Réaliser une application qui émet la première note de votre mélodie pendant 5 secondes. Q14. Réaliser la mélodie complète avec la méthode du DDS.