Aller au contenu

Very High Speed Integrated Circuit Hardware Description Language/Utiliser un processeur externe

Leçons de niveau 16
Une page de Wikiversité, la communauté pédagogique libre.
Début de la boite de navigation du chapitre
fin de la boite de navigation du chapitre
En raison de limitations techniques, la typographie souhaitable du titre, « Very High Speed Integrated Circuit Hardware Description Language : Utiliser un processeur externe
Very High Speed Integrated Circuit Hardware Description Language/Utiliser un processeur externe
 », n'a pu être restituée correctement ci-dessus.

Nous allons présenter dans ce chapitre un certain nombre de solutions consistant à déporter le processeur vers l'extérieur. Quand nous avons commencé l'écriture de ce livre nous ne pensions pas en arriver là... mais quelques prises de consciences nous ont fait changer d'avis :

  • la baisse continue des prix des microcontrôleurs du commerce. On trouve maintenant des platines de développement 16/32 bits à moins de 20  (chez Texas Instrument notamment en 2015) et moins de 10  en 2022 pour un ESP32 malgré la crise des semi-conducteurs du Covid en 2020.
  • la réalisation de projets autour de la robotique mobile nous amène à augmenter la taille de notre processeur. Ainsi un processeur 32 bits permet de faire assez facilement des calculs en nombre flottant.
  • une étude de 2008 (EETimes 30 juillet 2008) montrait que seulement 1/3 des utilisations de FPGA utilisant un processeur utilisait ce processeur dans le FPGA. Les choses ont probablement changées depuis : il semble que l’on soit passé à 50% en 2014.

L'étude de EETimes ci-dessus tentait d'examiner des pistes pour interfacer les deux mondes du micro-contrôleur et celui du FPGA en soulignant qu’à priori aucun des deux n'est prévu pour cela.

Nous allons examiner dans ce chapitre les communications entre un processeur du commerce et le FPGA qui ne sera considéré donc que comme un périphérique. Dire périphérique ne veut pas dire sans aucune intelligence. Ainsi un petit processeur pourra se glisser dans ce FPGA et être responsable de la communication avec le processeur externe !

Les communications que nous envisageons d'étudier pour le moment sont le protocôle SPI et le protocole i2c. Le domaine des 32 bits sera peut être approfondi un jour prochain avec le bus External Bus Interface (EIB) que l’on peut rencontrer sur ce type de micro-contrôleur de type ARM.

Pour rendre ce chapitre intéressant à un public le plus diversifié possible, nous sommes obligés d’utiliser plusieurs architectures différentes allant du 8 au 32 bits. Nous espérons que, même si vous ne disposez que d'une architecture différente, vous trouviez ici suffisamment d'informations pour un portage utile pour vous. Nous rappelons que vous pouvez aussi rédiger un chapitre ou une simple section concernant votre architecture... ce qui pourrait être utile à d'autres lecteurs.

Les connecteurs PMod

[modifier | modifier le wikicode]

Les FPGA que nous utilisons sont sur des cartes d'évaluation réalisées par Digilent. Elles sont caractérisées par des extensions appelées PMod que nous allons présenter maintenant.

Utilisation simple des PMod

[modifier | modifier le wikicode]

Parmi les périphériques que l’on peut acheter pour les FPGA, il en existe un certain nombre avec des connecteurs PMod. Ils sont alors très faciles à mettre en œuvre avec ou sans câble. Le seul point qu’il faut surveiller est de ne pas le brancher à l’envers. Pour s'y repérer il suffit de savoir que d'un côté du connecteur vous avez tout au bout Vcc et à côté la masse gnd. Si vous repérez cela des deux côtés, c’est gagné. La photo ci-dessous, par exemple, montre la connexion de deux périphériques de puissance (non visibles) à la carte FPGA. Allez voir dans le chapitre Commande de robot mobile et périphériques associés d'autres photos disponibles.

Utilisation avec périphérique non adapté

[modifier | modifier le wikicode]

Nous avons déjà publié dans le chapitre Commande de robot mobile et périphériques associés une série de photos montrant l’utilisation d'un PMod pour connecter une manette Nunchuk. Nous en reprenons une ci-dessous.

Détails sur la connexion entre la Basys2 et la Nunchuk

Vu le positionnement de notre connecteur blanc sur le PMod, l'alimentation Vcc = 3,3 V se trouve à gauche du connecteur lorsqu'on le regarde de face. De toute façon, il est bon de se rappeler que Vcc est en bout. C'est le fil orange de la photo.

Début d’un principe
Fin du principe


Lorsque le connecteur PMod est double (c'est souvent le cas sur les cartes plus récentes comme Nexys 3, la nouvelle Basys 3 et d'autres encore) les deux Vcc sont superposés (en face à gauche).

Utilisation avec plaque à essai

[modifier | modifier le wikicode]

Cette façon de faire est à conseiller lorsque vous chercher à réaliser une connexion entre un de vos propre périphérique et une carte FPGA.

Panneau d’avertissement

La tension d'alimentation des FPGA est 3,3 V. Ne présentez jamais une tension de 5V sur une entrée FPGA.

Cette utilisation ne nécessite pas d'explication supplémentaire sinon que le mieux est d’utiliser des fils de connexions Digilent, ceux que l’on voit sur la photo entre la Basys2 et les commandes des moteurs. L'achat de périphériques PMod vous fournit automatiquement ce genre de connectique. Si vous n'avez pas l'intention d'investir dans des périphériques PMod, utilisez de simples câbles males-males pour plaques à essais.

Trouver les contraintes à mettre dans le fichier ucf

[modifier | modifier le wikicode]

Les fichiers ucf que l’on télécharge dans la page des platines FPGA sont suffisamment commentés pour être facilement utilisables. La convention pour les PMods doubles est que l’on commence par le haut (et du côté opposé à Vcc). Par exemple, si vous avez :

##JA
#NET "JA<0>"          LOC = "T12" | IOSTANDARD = "LVCMOS33";   #Bank = 2, Pin name = IO_L19P, Sch name = JA1
#NET "JA<1>"          LOC = "V12" | IOSTANDARD = "LVCMOS33";   #Bank = 2, Pin name = IO_L19N, Sch name = JA2  
#NET "JA<2>"          LOC = "N10" | IOSTANDARD = "LVCMOS33";   #Bank = 2, Pin name = IO_L20P, Sch name = JA3
#NET "JA<3>"          LOC = "P11" | IOSTANDARD = "LVCMOS33";   #Bank = 2, Pin name = IO_L20N, Sch name = JA4
#NET "JA<4>"          LOC = "M10" | IOSTANDARD = "LVCMOS33";   #Bank = 2, Pin name = IO_L22P, Sch name = JA7
#NET "JA<5>"          LOC = "N9"  | IOSTANDARD = "LVCMOS33";   #Bank = 2, Pin name = IO_L22N, Sch name = JA8
#NET "JA<6>"          LOC = "U11" | IOSTANDARD = "LVCMOS33";   #Bank = 2, Pin name = IO_L23P, Sch name = JA9
#NET "JA<7>"          LOC = "V11" | IOSTANDARD = "LVCMOS33";   #Bank = 2, Pin name = IO_L23N, Sch name = JA10
Connecteur spécifique des cartes de Digilent (FPGA et Microcontrôleurs)

alors JA<0> est en haut côté droit du connecteur PMod (lorsqu'on est en face), JA<1> est un cran vers la gauche ... JA<4> est en bas à droite ... et JA<7> est en bas à gauche avant la masse.

Panneau d’avertissement
  • Les numéro de gauche du fichier de contraintes (le 0 de JA<0> par exemple) ne correspondent pas aux numéros de broches de la figure : JA<0> correspond à JA1 (à droite). Ce sera toujours une source de confusion, mais il faut vous y habituer.
  • Tous les numéros dans les tableaux ci-dessous correspondent aux numéros du dessin.

Si on vous dit que le câblage du PMod a été choisi comme (voir plus loin par exemple) :

SPI -- -- MOSI MISO SCK SS
PMOD 12 (Vcc) 11 (GND) 10 9 8 7

cela veut dire que SS est en broche 7 du connecteur Pmod, c'est-à-dire en bas à droite.

Processeur ATMega avec Arduino et SPI

[modifier | modifier le wikicode]

Nous commençons par utiliser l'Arduino parce que c’est probablement une des architectures les plus utilisées actuellement parmi les architectures modestes de 8 bits. Elle est caractérisée par une facilité exemplaire de programmation et des prix attractifs (autour de 20 ). Ce prix ne fera que descendre dans les années suivantes.

Présentation de l'Arduino utilisé

[modifier | modifier le wikicode]

L'Arduino en général est décrit aussi dans un chapitre du livre sur les AVR de la Wikiversité. Mais il est décliné en plusieurs versions.

Nous avons choisi la Platine "Pro Micro - 3,3 V/8MHz" de chez Sparkfun. Ce choix est essentiellement lié au fait que la platine est en 3,3 V et donc directement compatible avec le FPGA, ce qui n’est pas le cas de la majorité des platines Arduino. L'inconvénient associé à cette baisse de tension d'alimentation est le passage de sa fréquence d'horloge de 16 à 8 MHz, ce qui reste largement suffisant pour ce que nous prévoyons de faire dans cette section.

Vous ne possédez pas cette platine

[modifier | modifier le wikicode]

Si vous avez déjà une platine Arduino, elle est probablement en 5V, donc pas compatible au niveau des tensions avec le FPGA. Ne vous découragez pas pour autant, les tensions peuvent être adaptées.

Les sorties du micro-contrôleur peuvent être adaptées avec un simple diviseur de tension avec deux résistances (10k et 20k) pour ne pas détériorer le FPGA. La sortie du FPGA peut être branchée directement en entrée du micro-contrôleur mais cela nécessite un test pour être sûr que ce dernier considère le 3,3 V comme un 1 logique.

On peut aussi réaliser une adaptation bidirectionnelle. Ce genre d'adaptation est décrit par exemple dans ce lien. Considérez particulièrement celle qui utilise un FET (2N7000) et deux résistance de 10k, adaptation que nous avons eu l’occasion de tester.

La conversion analogique/numérique

[modifier | modifier le wikicode]

Une des applications pratiques à l'interface FPGA micro-contrôleur est l’utilisation des convertisseurs analogiques numériques présents dans la majorité de ces derniers. C'est ce que nous avions l'intention de réaliser dans le projet PMod Processeur pour une liaison série sur la Basys 2. Notez que cette technique existe aussi dans certaines cartes FPGA comme la MOJO 3.0. En effet cette carte est architecturée autour d'un ATMega32U4 et d'un FPGA Spartan6. Il est possible de récupérer les valeurs des convertisseurs Analogiques Numériques dans le FPGA.

Utiliser le langage Arduino pour lire une valeur analogique est très simple. Il existe une primitive appelée "analogRead". Rappelons pour être complet que les convertisseurs des ATMega sont sur 10 bits.

Complément sur l'installation Linux

[modifier | modifier le wikicode]

Le site de Sparkfun, le hookup Guide n’est pas complet pour la programmation de la Platine "Pro Micro - 3,3 V/8MHz". Ajouter les cartes sparkfun à l'aide du fichier fourni ne suffit pas. Des lignes sont à mettre dans le fichier "46-arduino.rules" dans /etc/udev/rules.d :

ACTION!="add|change", GOTO="mm_usb_device_blacklist_local_end"
SUBSYSTEM!="usb", GOTO="mm_usb_device_blacklist_local_end"
ENV{DEVTYPE}!="usb_device",  GOTO="mm_usb_device_blacklist_local_end"

ATTRS{idVendor}=="1b4f" ATTRS{idProduct}=="9204", ENV{ID_MM_DEVICE_IGNORE}="1"
ATTRS{idVendor}=="1b4f" ATTRS{idProduct}=="9203", ENV{ID_MM_DEVICE_IGNORE}="1"

LABEL="mm_usb_device_blacklist_local_end"

Suivies par un

sudo service udev restart

elles permettent une programmation et une utilisation de la liaison série.


Présentation du protocole SPI

[modifier | modifier le wikicode]

La programmation SPI dans le monde Arduino est facile. Mais sa mise en œuvre avec un FPGA nécessite une bonne compréhension de ce protocole.

L'article Serial Peripheral Interface de Wikipédia présente le protocole correspondant.

Des étudiants de l'IUT de Troyes ont travaillé sur ce type de projet et ont écrit quelques lignes ici.

La programmation SPI

[modifier | modifier le wikicode]

La programmation SPI du côté Arduino ne présente donc pas de difficulté particulière.

Voici donc un programme Maître (langage C) d'exemple :

#include <SPI.h>
//**** Version pour Sparkfun Pro-micro {{Unité|3.3|{{Abréviation|V|volt}}}}
//**** Horloge 8MHz
char dataToSend=0xA5; 
void setup (void) {
// Put SCK, MOSI, SS pins into output mode
// also put SCK, MOSI into LOW state, and SS into HIGH state.
  pinMode(10,OUTPUT); // SS not dedicated
  pinMode(16,OUTPUT); // MOSI
  pinMode(14,INPUT);  // MISO
// ensure SS stays high for now
  digitalWrite(10, HIGH);
// Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();
// Slow down the master a bit
   SPI.setClockDivider(SPI_CLOCK_DIV2);
//little indian or big indian ?
// SPI.setBitOrder(MSBFIRST);
// SPI.setBitOrder(LSBFIRST);
// SPI.setDataMode(SPI_MODE0);
  delay(100);
} // end of setup
 
void loop (void) {
//déclaration variable
  unsigned char recievedData;
// enable Slave Select (SS is pin 10)
  digitalWrite(10, LOW);
// transmission réception
  recievedData=SPI.transfer(dataToSend);
  delay(10);
  digitalWrite(10, HIGH);
// 1 seconds delay
  delay(1000);
  dataToSend++;
} // end of loop

Il peut être utilisé pour un début d'exploration.

Si vous voulez tester la communication bidirectionnelle du SPI, remplacez la boucle ci-dessus par celle-ci :

void loop (void) {
//déclaration variable
  unsigned char recievedData;
// enable Slave Select
  digitalWrite(10, LOW);
// SS is pin 10
  recievedData=SPI.transfer(dataToSend);
// Serial.println(dataByte,DEC);
  delay(10);
  digitalWrite(10, HIGH);
  dataToSend = recievedData;
  delay(1000);
// 1 seconds delay
}

Cette version bidirectionnelle avec une division seulement par deux de l'horloge a été testée en échange SPI avec une Nexys 3 avec succès (recopie des interrupteurs sur les LEDs avec une seconde de retard à cause du delay qui peut être naturellement supprimé).

Examinons donc maintenant ce que nous devons faire côté FPGA pour y réaliser un esclave SPI.

Esclave SPI sur FPGA

[modifier | modifier le wikicode]

Nous avons décidé de ne pas construire notre propre esclave mais d’en chercher un sur opencore : SPI Master Slave de Jonny Doin. Téléchargez-le. Nous avons ensuite écrit un composant général contenant cet esclave que voici :

Ce qui est donné ci-dessus permet un échange bidirectionnel entre l'Arduino Maître et le FPGA esclave.

Le fichier de contrainte correspondant est (pour une Nexys3) présenté dans la boite déroulante ci-dessous :

Il vous montre que l’on a utilisé le connecteur PMod nommé JC (partie basse).

Le câblage du PMod a été choisi comme :

SPI -- -- MOSI MISO SCK SS
PMOD 12 (Vcc) 11 (GND) 10 9 8 7

et nous avons utilisé la partie inférieure du connecteur en reliant la masse mais pas la source de tension : le FPGA et l'Arduino ont tous les deux leur propre alimentation par l'USB.

Le site de Sparkfun, le hookup Guide, vous permet de déduire une connexion que l’on représente dans un tableau qui met en correspondance les broches du Sparkfun Pro Micro avec le PMOD de Digilent pour un bon fonctionnement.

Sparkfun Pro micro -- GND 16 14 15 10
PMOD (Digilent) 12 (Vcc) 11 (GND) 10 9 8 7

En clair les deux tableaux peuvent être fusionnés comme ceci :

SPI -- -- MOSI MISO SCK SS
PMOD 12 (Vcc) 11 (GND) 10 9 8 7
Sparkfun Pro micro -- GND 16 14 15 10

Ce tableau signifie que la broche Arduino (Sparkfun) qui porte le numéro 10 est reliée à la broche numéro 7 du PMod. Cette broche est à l'opposé de Vcc sur le connecteur PMod inférieur.

Vous serez obligé d'adapter la partie PMOD à votre carte FPGA et à votre choix de PMOD dans votre fichier ucf. Il est donné plus haut mais nous rappelons la partie concernée :

##JC
#Connecteur bas pour Pro Micro Sparkfun
NET "ss"          LOC = "G1"  | IOSTANDARD = "LVCMOS33";   
NET "sck" CLOCK_DEDICATED_ROUTE = FALSE |LOC = "J7"  | IOSTANDARD = "LVCMOS33";   
NET "miso"          LOC = "J6"  | IOSTANDARD = "LVCMOS33";   
NET "mosi"          LOC = "F2"  | IOSTANDARD = "LVCMOS33";  

Le connecteur PMod sur la carte Nexys 3 qui nous a servi à faire les essais est double : une partie haute et une partie basse. C'est pour cela qu’apparaît "Connecteur bas" dans les commentaires de ce fichier ucf.


Projets associés

[modifier | modifier le wikicode]

Processeur ATMega avec Arduino et protocole I2C

[modifier | modifier le wikicode]

Nous utiliserons encore la Platine "Pro Micro - 3,3 V/8MHz" de chez Sparkfun et restons donc dans le monde Arduino.

Nous allons nous intéresser maintenant au protocole I2C. L'intérêt de ce protocole par rapport au SPI est la notion d'adresse : chaque périphérique a une adresse particulière. Cela permet de réaliser plusieurs périphériques dans notre FPGA et de les adresser individuellement. En principe le SPI nécessite une ligne SS (Slave Select) par esclave et cela prend vite des broches. L'étude de la manette Nunchuk dans ce livre utilisait le FPGA comme i2c maître alors que nous allons plutôt l’utiliser en esclave dans cette section.

Le dernier esclave est trop rudimentaire pour être utilisé, le premier nécessite un travail important. Nous choisissons donc le deuxième même s'il est en Verilog. Rappelons à ce propos que nous avons commencé à écrire un chapitre sur le sujet (mariage VHDL et Verilog) qui n’est pas encore très avancé. Le deuxième a été choisi aussi parce qu’il dispose de 4 octets en entrée et de 4 octets en sortie. Cela nous semble suffisant même si l'exemple donné plus loin n'en utilise qu'un seul en entrée et sortie.

Pour information la librairie Arduino pour l'i2c fixe la fréquence du maître à 100 kHz. Si vous voulez une fréquence plus grande il faudra :

  • changer la fréquence dans la librairie Arduino
  • ou utiliser votre propre librairie C

Le câblage a été choisi comme :

I2C -- -- -- -- SCL SDA
Sparkfun Pro micro -- GND -- -- 3 2
PMOD (Digilent) 12 (Vcc) 11 (GND) 10 9 8 7

Programmes Arduino de lecture/écriture pour l'esclave FPGA

[modifier | modifier le wikicode]

Nous allons distinguer dans un premier temps la lecture et l'écriture.

Écrire une valeur sur les LEDs

[modifier | modifier le wikicode]

La situation est donc la suivante : on dispose d'un cœur FPGA réalisant un esclave i2c d'adresse 0x3C. Il est câblé de telle manière qu'un de ses registres de sortie (il peut en avoir jusque 4) est relié à des leds.

Le programme suivant :

#include <Wire.h>

void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
}

byte x = 0;

void loop(){
// transmit to device 0x3C (adresse choisie en dur dans le cœur FPGA)
  Wire.beginTransmission(0x3C);
// transmet l'adresse d'écriture qui varie entre 0 et 3 :
  Wire.write(0);  
  Wire.write(x);              // sends one byte 
  Wire.endTransmission();    // stop transmitting
  x++;
  delay(500);
}

fonctionne parfaitement avec le cœur FPGA décrit plus loin.

Écrire une valeur sur les LEDs en C pur

[modifier | modifier le wikicode]

Nous avons testé le programme ci-dessous avec succès. Il utilise une librairie simple écrite par Peter Fleury :

Il est naturellement possible de mélanger le langage Arduino avec cette librairie, par exemple comme ceci :

void setup(){
  i2c_init();
}
void loop() {
  static unsigned char x=0;
    i2c_start(0x3C<<1);
    i2c_write(0);
    i2c_write(x);
    i2c_stop();
    x++;  
    delay(500);
}

Pour ceux qui veulent la librairie complète, la voici :

Lecture de données en provenance de l'esclave

[modifier | modifier le wikicode]

L'esclave est un FPGA pour lequel 4 registres sont disponibles en lecture. Le programme suivant :

#include <Wire.h>

void setup() {
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
}

void loop() {
  Wire.beginTransmission(0x3C);
  Wire.write(4); // addresse du premier registre à lire 
  Wire.requestFrom(0x3C, 4);    // request 4 bytes from slave device 0x3C
   
  while(Wire.available())    // slave may send less than requested
  { 
    char c = Wire.read(); // receive a byte as character
    Serial.println(c,HEX);         // print the character
  }
  Wire.endTransmission(); 
  delay(2000);
}

permet de récupérer les valeurs des interrupteurs et les valeurs câblées en dur dans notre périphérique i2c.

Une question vient peut-être à l'esprit du lecteur : comment réaliser Wire.requestFrom(0x3C, 4); avec la librairie C ?

Voici donc un exemple qui mélange le langage Arduino et le C (surtout pour avoir à disposition la liaison série) :

void setup(){
  i2c_init();
  Serial.begin(9600);
}
void loop() {
  static unsigned char x=0;
    unsigned char c;
  // on commence par dire que l’on va lire à partir de l'adresse 4
    i2c_start(0x3C<<1);
    i2c_write(4);
    i2c_stop();
  // on dit ensuite que l’on va lire 4 octets
    i2c_start((0x3C<<1));
    i2c_write(4);
    i2c_stop();
  // on envoie ensuite un ordre de lecture
    i2c_start((0x3C<<1)|0x01);
  // et on lit maintenant
    c=i2c_readAck();
    Serial.print(c,HEX);
    c=i2c_readAck();
    Serial.print(c,HEX);
    c=i2c_readAck();
    Serial.print(c,HEX);
    c=i2c_readNak();
    Serial.println(c,HEX);
  // on termine le tout
    i2c_stop();
    x++;  
    delay(2000);
}

Hormis un petit problème sur notre carte FPGA avec un bouton switch, tout semble fonctionner normalement.


Depuis le temps que nous en parlons, il est temps maintenant de présenter notre cœur FPGA comme esclave i2c.

Un Cœur FPGA pour réaliser un esclave I2C (en Verilog)

[modifier | modifier le wikicode]

Le cœur FPGA est celui de chez Opencores (i2c slave) avec comme seul changement la fréquence d'horloge de notre Nexys 3 à 100 MHz dans i2c_slave_define.v et un module global dans i2cSlaveTop.v :

`include "i2cSlave_define.v"
module i2cSlaveTop (
  clk,
  rst,
  sda,
  scl,
  sw,
  leds8
);
input clk;
input rst;
inout sda;
input [7:0] sw;
input scl;
output [7:0] leds8;

i2cSlave u_i2cSlave(
  .clk(clk),
  .rst(rst),
  .sda(sda),
  .scl(scl),
  .myReg0(leds8),
  .myReg1(),
  .myReg2(),
  .myReg3(),
  .myReg4(sw),
  .myReg5(8'h34),
  .myReg6(8'h56),
  .myReg7(8'h78)

);
endmodule

On a donc modifié l'original comme suit :

  • remplacer reg0 par leds8 qui pour nous sera directement relié aux 8 leds de notre carte FPGA
  • ajouté sw comme premier registre d'entrée qui sera directement relié à nos interrupteurs de la carte Nexys 3

Pour information, l'adresse du périphérique est fixée en dur dans un fichier et non pas au moment de l'instanciation. Cela ne permet donc pas d’utiliser deux périphériques i2c dans un même FPGA sans changement... C'est un peu dommage, mais nous changerons peut-être cela dans le futur...

Le fichier ucf correspondant montre que l’on utilise les switchs comme entrée et les 8 leds comme sortie.

Bien sûr, chaque type de carte aura son fichier ucf. Mais cet exemple permettra une adaptation plus facile. Pour faciliter encore sa compréhension rappelons à l'aide de tableaux le câblage choisi.

Le câblage du PMod a été choisi avec la partie inférieure du connecteur en reliant la masse, ce que montre le tableau suivant :

i2c -- -- -- -- SCL SDA
Sparkfun Pro micro -- GND -- -- 3 2
PMOD (Digilent) 12 (Vcc) 11 (GND) 10 9 8 7

Évaluation grossière de la vitesse de transmission

[modifier | modifier le wikicode]

Nous avons parlé d'une fréquence d'horloge du maître de 100 kHz mais qu'en est-il de la fréquence d'émission de de réception des 4 octets de notre cœur ?

La documentation officielle que l’on trouve avec le cœur fait état de :

  • 8 octets à émettre au minimum pour écrire les 4 octets
  • 7 octets bidirectionnels pour la réception

En admettant que l'envoi d'un octet est équivalent à l'envoi de 10 bits (à cause du start et stop), la fréquence maximale d'échange est donc :

Utiliser ce mode de dialogue en robotique mobile où l’on a besoin souvent d'informations sur les capteurs de 20 à 50 fois par seconde est donc envisageable.

A ce point nous avons à disposition deux modes de dialogues entre un processeur et un FPGA : le SPI et I2C. Ces deux modes sont très intéressants car pratiquement tous les microcontrôleurs ont à disposition des périphériques qui gèrent ces deux protocôles.


Nous allons maintenant complètement changer de processeur pour donner d'autres exemples.

Processeur MSP 430 et SPI

[modifier | modifier le wikicode]

Le microcontrôleur MSP430 fait partie des architectures 16 bits. Il entre en concurrence avec les PIC24F. Sa particularité est sa gamme faible consommation.

Présentation du MSP430

[modifier | modifier le wikicode]

Nous allons utiliser un MSP430 pour ce projet qui va consister à récupérer les valeurs données par le processeur dans le FPGA.

Le MSP430 est un processeur 16 bits présenté rapidement dans un chapitre de ce livre, qui est caractérisé par sa faible consommation. Il existe un kit appelé "Launchpad" à faible prix (environ 10 ). Son gros intérêt, à part son prix, est une tension de 3,3 V directement compatible avec le FPGA et un environnement de développement identique à l'Arduino.

Installer Energia sous Linux

[modifier | modifier le wikicode]

Si vous téléchargez les binaires chez energia.nu, décompressez-les et votre environnement est en état de marche pour compiler.

Pour téléverser dans les processeurs, il faut ajouter dans un fichier 99-ti-launchpad.rules (dans /etc/udev/rules.d ) mettre :

# CC3200 LaunchPad
SUBSYSTEM=="usb", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="0660", GROUP="dialout", 
RUN+="/sbin/modprobe ftdi-sio" RUN+="/bin/sh -c '/bin/echo 0451 c32a > /sys/bus/usb-serial/drivers/ftdi_sio/new_id'"

# MSP-EXP430G2 and MSP-EXP430FR5739 LaunchPad
ATTRS{idVendor}=="0451", ATTRS{idProduct}=="f432", MODE="0660", GROUP="dialout"
# MSP-EXP430F5529LP and MSP-EXP430FR5969 LaunchPad
ATTRS{idVendor}=="1cbe", ATTR{idProduct}=="00fd", MODE="0660", GROUP="dialout"

# EK-TM4C123GXL, EK-TM4C1294XL and EK-LM4F120XL LaunchPad
ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="0660", GROUP="dialout"

A ce stade, seule la ligne correspondant à notre launchPad MSP-EXP430G2 est nécessaire. Mais nous utiliserons un peu plus loin, dans ce chapitre, le 32 bits ARM Cortex M4 TM4C123GXL. Autant faire d'une pierre deux coups.

Un redémarrage du service udev est alors nécessaire. La commande

sudo service udev restart

fera alors l'affaire.

La conversion analogique/numérique

[modifier | modifier le wikicode]

Nous parlons de la conversion analogique/numérique ici car c’est une application naturelle à l'interfaçage d'un FPGA avec un microcontrôleur. Les convertisseurs Analogiques Numériques du MSP430 sont des convertisseurs sur 10 bits (comme pour les Arduinos) et fonctionnent jusqu'à 200 000 fois par seconde (Greater than 200-ksps maximum conversion rate). Ils peuvent passer à 12 bits pour certaines familles du MSP430.

Pour éviter à nos étudiants connaissant l'Arduino de se perdre dans un nouvel environnement, nous allons utiliser un environnement équivalent qui s’appelle Energia. Le langage correspondant est identique.

Comme pour l'Arduino, lire une valeur analogique est très simple. Il existe aussi une primitive appelée "analogRead".

Le protocole SPI

[modifier | modifier le wikicode]

La programmation SPI, comme présentée dans le projet précédent, est facile. Nous ne reviendrons pas sur la présentation de ce protocole (voir projet correspondant avec l'Arduino de ce chapitre).

Pour faire fonctionner le protocole SPI il faut un maître et un esclave. Commençons par un maître réalisé avec le MSP430.

Le maître avec un MSP430

[modifier | modifier le wikicode]

Voici un squelette de programme pour commencer à réfléchir :

/*************************
* Carte SD ----- Launchpad
* GND ----------- GND
* +3.3 ---------- Vcc
* CS ------------ P2.0 (8)
* MOSI ---------- P1.7 (15)
* SCK ----------- P1.5 (7)
* MISO ---------- P1.6 (14)
*
**************************/ 
#include <SPI.h>

const int chipSelectPin = 8; // P2.0
char dataToSend=0xA5; 
void setup(){
  pinMode(chipSelectPin, OUTPUT);
  pinMode(15,OUTPUT);
  pinMode(14,INPUT);
// start the SPI library: 
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV128);
    
  delay(100);
}

void loop() {
  char recievedData;
  digitalWrite(chipSelectPin, LOW);  
  recievedData=SPI.transfer(dataToSend); //Send register location
  delay(10);
  digitalWrite(chipSelectPin, HIGH);
  delay(1000);
  dataToSend++;
}

Notre esclave va être présenté maintenant. Il s'agit d'une carte FPGA Nexys3 doté d'un spartan6.

Esclave SPI sur FPGA

[modifier | modifier le wikicode]

La notion d'esclave SPI enfouie dans un FPGA a été abordée dans une précédente section.

Le câblage du PMod a été choisi encore comme :

SPI -- -- MOSI MISO SCK SS
PMOD 12 (Vcc) 11 (GND) 10 9 8 7
MSP430 -- GND P1.7 P1.6 P1.5 P2.0


Projets associés

[modifier | modifier le wikicode]

CORDIC et MSP430

[modifier | modifier le wikicode]

CORDIC est déjà évoqué dans :

Nous ne reprendrons donc pas la théorie ici. Rappelons quand même que nous allons utiliser un format virgule fixe sur 16 bits de type Q3.13, ce qui veut dire que la partie décimale comporte 13 bits après la virgule. Si l’on se rapporte au décimal, cela fait 3 digits corrects après la virgule.

Version logicielle de CORDIC

[modifier | modifier le wikicode]

Nous avons repris le programme Arduino et modifié un peu les types, particulièrement le type int. En effet, la taille du type int nécessite de se plonger dans la documentation du compilateur. Ne pas le faire nous expose à des erreurs comme cela nous est arrivé avec le type "long int" qui est sur 32 bits sur les AVRs mais 16 bits sur les PIC. Heureusement le compilateur du GNU nous permet de définir la taille des types de manière univoque et c’est ce que nous avons fait dans le programme ci-dessous.

Gardez à l'esprit que ce qui est publié ci-dessus est fonctionnel pour le MSP430. Vous ne devrez tenir compte de la remarque ci-dessous que si vous voulez l’utiliser dans l'environnement Arduino (ou avr-gcc en général).


Cœur FPGA CORDIC interfacé au MSP430 par une liaison SPI

[modifier | modifier le wikicode]

Nous allons maintenant nous intéresser à l'interfaçage d'un cœur matériel CORDIC dans un FPGA avec un processeur externe de type MSP430. Nous avons choisi pour cela le SPI plutôt qu'un autre protocole car il nous semble être le plus rapide (horloge à 8MHz =fréquence quartz/2).

La partie matérielle est aussi donnée (sans le cœur SPI) que l’on peut trouver sur Internet.

La version présentée est fonctionnelle mais peut être largement améliorée puisque seul le sinus est retourné au MSP 430 par la liaison SPI. Nous laissons le soin aux lecteurs de perfectionner cet ensemble puisque, le but ici, est simplement de vous montrer comment cette liaison est possible.


Il y a d'autres moyens de communications à explorer avec le MSP430. Par exemple, le MSP430 contient une gestion DMA certes limitée, mais nous n'avons pas suffisamment détaillé sa documentation pour voir s'il était possible de l’utiliser pour notre problème. Ce problème ne sera probablement jamais exploré ici car le msp430 launchpad est remplacé progressivement par le msp432 launchpad étudié un peu plus loin.

Nous allons maintenant entrer dans le domaine des 32 bits. Ce qui a été vu précédemment sur le SPI et l'i2c reste d'actualité, mais nous allons explorer d'autres modes de transferts.

Utilisation du TM4C123GH6PM (Tiva C LaunchPad)

[modifier | modifier le wikicode]

Nous entrons maintenant dans le domaine des processeurs 32 bits avec un TM4C123GH6PM qui est un ARM Cortex 4. Sa documentation officielle se trouve facilement sur Internet. Son choix est lié à l’existence d'une platine d'évaluation ((en)Tiva-C LaunchPad) avec :

  • un prix de moins de 17  (13,23  HT chez Farnel)
  • un environnement de développement du type Arduino appelé Energia
  • une fixation plus aisée que pour le LaunchPad MSP430 (point de vue qui reste discutable)

A l’heure où nous écrivons ces lignes (octobre 2014) l'environnement Arduino ne supporte le DUE (32 bits) qu'en version beta et tout ceci pour un prix approchant les 40 . Le seul concurrent que nous voyons au Tiva-C LaunchPad est la Teensy 3.1. Elle se programme directement dans l'environnement Arduino (avec un Plugin ajouté) et coûte moins de 20 .

Quatre années plus tard (2018) l'environnement Arduino supporte en plus le Blue Pill STM32 qui est une carte 32 bits que l'on trouvait aux alentours de 1,1  à l'époque. Aujourd'hui (2020) le prix est plutôt autour de 1,5 . Il existe une version un peu plus chère mais avec 128/256 ko de Flash (contre 64ko pour le Blue Pill).

En 2019 (et peut être probablement avant) on pouvait trouver une autre famille de 32 bits, l'ESP32. Il s'agit d'un double cœur d'un processeur 32 bits qui n'est pas un ARM 32 bits. Il est aussi programmable à partir de l'environnement Arduino pour un prix aux alentours de 3 .

En 2020 un nouveau processeur fait son apparition. Il s'agit du risc v 32 bits avec des cartes autour de 4 . Une autre version double cœur 64 bits autour de 20 , est disponible, le tout encore programmable avec l'environnement Arduino.

Même si nous abordons le domaine des 32 bits, nous ne pourrons en aucun cas concurrencer les FPGA de type (en) Zynq de chez Xilinx en mettant un processeur externe. Si la vitesse est votre problème, prenez un Zynq. Si la simplicité est votre problème, envisagez un processeur externe.

La documentation de la platine que nous allons utiliser se trouve ICI sur le site Energia. Cela laisserait penser que Texas Instrument apporte un peu d'aide au développement d'Energia. Robert Wessels qui développe Energia depuis 2012 semble faire partie du personnel de Texas Instrument. Côté concurrence, vu la vitesse de développement de l'IDE Arduino ce ne serait pas le cas d'Atmel ? Nous parlons bien au conditionnel car nous n'avons aucune information officielle sur le sujet. Nous croyons savoir qu'Atmel serait actif pour le développement du compilateur avr-gcc. Chacun sa stratégie. Laissons donc ces stratégies commerciales aux professionnels pour entrer dans ce que nous connaissons le mieux, la technique.


Nous allons commencer par étudier notre vieil ami, le protocole SPI.

Le protocole SPI

[modifier | modifier le wikicode]

La programmation SPI est la même que pour le MSP430 puisque l'environnement de développement est identique. Nous donnons quand même le programme puisque le brochage change. Faites un effort avec la documentation de la platine pour constater la bonne utilisation du SPI.

/*************************
* Carte SD ----- Launchpad
* TM4C123G (ARM)
* GND ----------- GND
* +3.3 ---------- Vcc
* CS ------------ PB5 (PB_5)
* MOSI ---------- PB7 (PB_7)
* SCK ----------- PB4 (PB_4)
* MISO ---------- PB6 (PB_6)
*
**************************/ 
#include <SPI.h>

const int chipSelectPin = PB_5; // P2.0
int dataToSend=0xAA; 
void setup(){
  char i;
  pinMode(chipSelectPin, OUTPUT);
  pinMode(PB_7,OUTPUT);
  pinMode(PB_6,INPUT);  
// start the SPI library:
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  delay(100);
}

void loop() {
  unsigned char recievedData;
// recupération d'une valeur quelconque de quelque part
  digitalWrite(chipSelectPin, LOW);  
  recievedData=SPI.transfer(dataToSend); //Send register location
  delay(10);
  digitalWrite(chipSelectPin, HIGH);
  delay(1000);
  //dataToSend=recievedData;
  dataToSend++;
}

Ce programme a été testé avec notre esclave SPI sur FPGA décrit précédemment.

Câblage utilisé

[modifier | modifier le wikicode]

On a utilisé le connecteur PMod nommé JC (partie basse) comme ceci :

Le câblage du PMod a été choisi comme :

SPI -- -- MOSI MISO SCK SS
PMOD 6 (Vcc) 5 (GND) 4 3 2 1

et donc le fichier ucf correspondant pour la partie haute du connecteur JC :

#JC
#Connecteur haut pour Tiva C LaunchPad
NET "ss"          LOC = "H3"  | IOSTANDARD = "LVCMOS33";   
NET "sck" CLOCK_DEDICATED_ROUTE = FALSE | LOC = "L7"  | IOSTANDARD = "LVCMOS33";  
NET "miso"          LOC = "K6"  | IOSTANDARD = "LVCMOS33";   
NET "mosi"          LOC = "G3"  | IOSTANDARD = "LVCMOS33"; 

Côté TM4C123G on câble :

Tiva C LaunchPad -- GND PB_7 PB_6 PB_4 PB_5
PMOD (Digilent) 6 (Vcc) 5 (GND) 4 3 2 1

Communication i2c

[modifier | modifier le wikicode]

Comme ce problème a été traité avec l'Arduino, nous allons faire une variation pour cette section. Nous allons utiliser un cœur i2c esclave écrit en VHDL. Nous avons fini par trouver un esclave i2c en VHDL... et très récemment un contrôleur i2c intelligent. Ce contrôleur développé par Mike Field mérite d’être étudié de près. Lui l'utilise dans quelques projets mais surtout en maître. Il nous faut donc comprendre son fonctionnement pour voir s'il n’est pas possible de l’utiliser en esclave.

Pour utiliser l'i2c sous Energia avec le TM4C123G on câble :

Périphérique i2c (numéro) -- GND SCL(3) SDA(3)
Tiva C LaunchPad -- GND PD0 PD1
PMOD (Digilent) 6 (Vcc) 5 (GND) 4 3

Il faut savoir que l’on utilise le périphérique i2c portant le numéro 3 en câblant ainsi. C'est celui qui est utilisé par la bibliothèque Energia par défaut.

Peut-on utiliser ĺa DMA pour les transferts bidirectionnels avec les FPGA ?

[modifier | modifier le wikicode]

La DMA permet des transferts directs entre périphériques et la mémoire RAM. Le module qui s'occupe de cela dans le processeur qui nous intéresse s’appelle μDMA. Il permet aussi des transferts directs de mémoire à mémoire mais nous ne nous y intéresserons pas.

Données du convertisseur Analogique Numérique vers le FPGA

[modifier | modifier le wikicode]

Dans cette section, on cherche à réaliser un transfert monodirectionnel : du processeur TM4C123GH6PM vers le FPGA.

La conversion Analogique numérique sur ce type de processeur se fait à une fréquence d'environ 260 kHz (temps de conversion 3,9 μs). La question que l’on va chercher à résoudre est de réaliser des transferts SPI de ces valeurs au fur et à mesure qu’elles arrivent par DMA, donc sans utiliser de temps processeur (ou presque).

La fréquence de 260 kHz donnée ne correspond pas à la fréquence d'horloge du SPI. En effet à chaque conversion il faut transmettre 12 bits (soit deux octets car l'unité de base du SPI est l'octet). Cela fait donc une fréquence minimum de l'horloge du SPI de 4,160 000 MHz.

Utiliser le tout nouveau MSP432 de Texas Instrument

[modifier | modifier le wikicode]

Même si le type de microcontrôleur le plus vendu reste le 8 bits, il y a encore de la place pour le MSP430. Pourtant Texas Instrument a décidé d'étoffer son offre faible consommation (MSP43X) par un nouveau venu le MSP432 en 2015). Celui-ci est un 32 bits et nous allons l'étudier maintenant. Ce qui nous a séduit avec ce processeur est la facilité avec laquelle on fait du multitâche avec l'environnement Energia. Il est très possible qu'au moment où vous lisiez ces lignes l’utilisation du multitâche puisse se faire avec d'autres processeurs de chez Texas Instrument.


Petit jeu de Pong avec carte Altera DE2-115 (Projet 2015/2016)

[modifier | modifier le wikicode]

Pour changer un peu de FPGA, nous allons cibler une carte Altera. C'est la carte FPGA qui s'occupe de l’affichage sur l'écran VGA mais le processeur externe s'occupe des déplacements de la balle et de la raquette. Nous donnons un code simple qui dessine une balle et une raquette sur un écran VGA (les deux sont matérialisés par des rectangles).

Nous rappelons que le code donné ci-dessus nécessite l'ajout d'un fichier spi_slave.vhd dans le projet, fichier que l’on trouve chez Opencores.org : SPI Master Slave de Jonny Doin.

Cette version utilise un échange SPI de 32 bits. Les données sont supposées être :

  • 10 bits de poids faible (b9 à b0) pour la coordonnée x de la balle
  • 10 bits de poids moyens (b19 à b10) pour la coordonnée y de la balle
  • 10 bits de poids forts (b29 à b20) pour la coordonnée x de la raquette

Une version d'essai du programme est :

#include <SPI.h>
//**** Version pour MSP432 {{Unité|3.3|{{Abréviation|V|volt}}}}
uint32_t dataToSend=0x00; 
void setup (void) {
// Put SCK, MOSI, SS pins into output mode
// also put SCK, MOSI into LOW state, and SS into HIGH state.
  pinMode(7,OUTPUT); //SCK
  pinMode(18,OUTPUT); // SS dedicated
  pinMode(15,OUTPUT); // MOSI
  pinMode(14,INPUT);  // MISO
// ensure SS stays high for now
  digitalWrite(18, HIGH);
  digitalWrite(7, LOW);
  digitalWrite(7, HIGH);
  digitalWrite(7, LOW);
  delay(1);
  digitalWrite(15, LOW);
// Then put SPI hardware into Master mode and turn SPI on
  SPI.begin();
// Slow down the master a bit
   SPI.setClockDivider(SPI_CLOCK_DIV2);
//little indian or big indian ?
// SPI.setBitOrder(MSBFIRST);
// SPI.setBitOrder(LSBFIRST);
// SPI.setDataMode(SPI_MODE0);
  delay(100);
} // end of setup

void loop (void) {
//déclaration variable
  uint16_t recievedData;
// enable Slave Select (SS is pin 10)
  digitalWrite(18, LOW);
// transmission réception des 32 bits
  recievedData=SPI.transfer(dataToSend>>24);
  recievedData=SPI.transfer(dataToSend>>16);
  recievedData=SPI.transfer(dataToSend>>8);
  recievedData=SPI.transfer(dataToSend);
  digitalWrite(18, HIGH);
  dataToSend +=5;
  if ((dataToSend & 0x3FF) > 639) dataToSend &= ~0x3FF;
  dataToSend += 0x00001400;
  if ((dataToSend & 0xFFC00) > 0x6C000) dataToSend &= ~0xFFC00;
  // 50 milliseconds delay
  delay(50);
} // end of loop

Les nombres hexadécimaux bizarres apparaissant dans ce code sont liés aux conventions pour les coordonnées des objets balle et raquette.

Il y a au moins deux façons de contourner le problème de cette remarque de manière logicielle :

  • faire un décalage d'un bit vers la gauche avant l'envoi SPI : on perd alors systématiquement le bit de poids faible.
  • considérer une autre répartitions des 3x10 bits comme ceci :

Répartition espérée :

b31
b30
b29
b28..b21
b20
b19
b18..b11
b10
b9
b8..b1
b0
X
X
RaqX9
RaqX8..RaqX1
RaqX0
BallY9
BallY8..BallY1
BallY0
BallX9
BallX8..BallX1
BallX0

Le matériel réalise donc la répartition des 3 données de 10 bits comme montré ci-dessus. Mais un problème matériel (perte du bit de poids faible) nous oblige à considérer que la répartition est décalée d'un bit vers la gauche.

Répartition réalisée d'un point de vue logicielle :

b31
b30
b29..b22
b21
b20
b19..b12
b11
b10
b9..b2
b1
b0
X
RaqX9
RaqX8..RaqX1
RaqX0
BallY9
BallY8..BallY1
BallY0
BallX9
BallX8..BallX1
BallX0
X

Voici le code associé :

void loop (void) {
//déclaration variable
  uint16_t recievedData;
// enable Slave Select (SS is pin 10)
  digitalWrite(18, LOW);
// transmission réception
// dataToSend <<= 1;
  recievedData=SPI.transfer(dataToSend>>24);
  recievedData=SPI.transfer(dataToSend>>16);
  recievedData=SPI.transfer(dataToSend>>8);
  //delay(1);
  recievedData=SPI.transfer(dataToSend);
  //delay(1);
  digitalWrite(18, HIGH);
// dataToSend >>= 1;
  dataToSend +=10; // 5<<1
  if ((dataToSend & 0x7FF) > (639<<1)) dataToSend &= ~0x7FF;
  dataToSend += 0x00002800;
  if ((dataToSend & 0x1FF800) > (400<<11)) dataToSend &= ~0x1FF800;
  // 50 milliseconds delay
  delay(50);
} // end of loop

Pour éviter toute cette gymnastique, nous allons réaliser des sous-programmes utiles pour notre projet.

Écriture de sous-programmes bien utiles

[modifier | modifier le wikicode]

Le fait de construire une variable unique de 32 bits contenant 3 positions de 10 bits complique un peu le design des sous programmes. Nous proposons deux sous-programmes pour gérer respectivement les positions de la balle et de la raquette.

Commençons par le positionnement de la balle :

//**********************************************************************************************************
// function setBallXY()
// purpose: put the ball with x and y coordinates
// arguments:
// corresponding x and y coordinates and the old 32-bit value
// return:32-bit ready for SPI
// note:all value are one bit left shifted because of hardware problem
//**********************************************************************************************************
uint32_t setBallXY(int16_t x,int16_t y,uint32_t old) {
  uint32_t result=old;
  // on met à zéro la partie que l’on va changer
  result &= ~0x001FFFFF;
  if ((x > 0) && (x < (630<<1))) result |= (x<<1);
  if ((y > 0) && (y < (460<<11))) result |= (y<<11); 
  return result;
}

Voici comment il peut être utilisé :

void loop (void) {
//déclaration variable
  uint8_t recievedData;
  static int16_t ballX=40,ballY=40;
  static int16_t deltaX=5,deltaY=5;
// enable Slave Select (SS is pin 10)
  digitalWrite(18, LOW);
  recievedData=SPI.transfer(dataToSend>>24);
  recievedData=SPI.transfer(dataToSend>>16);
  recievedData=SPI.transfer(dataToSend>>8);
  recievedData=SPI.transfer(dataToSend);
  digitalWrite(18, HIGH);  
  ballX += deltaX;
  ballY += deltaY; 
  if (ballX > 620) deltaX = -deltaX;
  if (ballX < 10) deltaX = -deltaX;
  if (ballY > 430) deltaY = -deltaY;
  if (ballY < 10) deltaY = -deltaY;
  dataToSend = setBallXY(ballX,ballY,dataToSend);
  // 50 milliseconds delay
  delay(50);
} // end of loop

Voici maintenant un sous-programme bien utile pour le mouvement de la raquette :

//**********************************************************************************************************
// function setPaddleX()
// purpose: put the paddle at x position
// arguments:
// corresponding x and y coordinates and the old 32-bit value
// return:32-bit ready for SPI
// note:all value are one bit left shifted because of hardware problem
//**********************************************************************************************************
uint32_t setPaddleX(int16_t x,uint32_t old) {
  uint32_t result=old;
  // on met à zéro la partie que l’on va changer
  result &= ~0x7FE00000;
  if ((x > 0) && (x < (630<<1))) result |= (x<<21);
  return result;
}

Améliorations

[modifier | modifier le wikicode]

L'objectif du projet est naturellement d'améliorer le matériel et sa programmation. Il serait bien, par exemple, d’utiliser une manette Nunchuck pour déplacer la raquette.

Essai d'une manette Nuncuk avec MSP432

[modifier | modifier le wikicode]

Nous n'avons pas encore essayé d’utiliser notre module matériel i2c que l’on a développé dans le projet Pacman en le portant pour Altera. Une des raisons est que nous ne savons pas comment utiliser des pull-up avec Altera (dans le fichier de contraintes). Une autre est le manque de temps... et une dernière est que nous avons l'intention d'abandonner l'i2c avec machine d'états pour le remplacer par ce processeur dédié. Cela aussi prendra du temps mais nous avons d'autres périphériques i2c en réserve, comme le MPU6050, qui seront plus facile à adapter avec ce processeur dédié à l'i2c. Ce périphérique pourrait d'ailleurs lui aussi être utilisé comme gamepad pour le jeu de pong que nous sommes en train de réaliser.

Puisque nous ne développons pas de matériel à ce stade, et que nous avons un processeur externe (MSP432) qui communique avec le FPGA nous pouvons essayer de communiquer avec la manette Nunchuk à l'aide de ce processeur.

Pour information, les programmes que l’on trouve pour l'Arduino pour lire une manette Nunchuk ne fonctionnent pas tels quels. Nous avons très vite suspecté le bit des données (SDA) parce que les valeurs reçues était toutes qu'avec des '1' partout :

  • 255 pour le joystick analogique
  • 1024 pour les accéléromètres
  • 1 pour chacun des boutons.

Nous avons essayé de forcer l'entrée des données avec une résistance de tirage vers Vcc et cela a fonctionné immédiatement. Voici donc le code correspondant :


Réunir tout le monde maintenant

[modifier | modifier le wikicode]

Tout ce que nous avons besoin pour mener le projet à bien est terminé du point de vue matériel. Seul le logiciel reste à développer sur le MSP432. Celui-ci doit permettre de déplacer la raquette grâce à la manette Nunchuk, de déteminer les rebonds de la balle sur cette même raquette.