« Very High Speed Integrated Circuit Hardware Description Language/Travail pratique/Autres projets pour ATMEL ATMega8 » : différence entre les versions

Contenu supprimé Contenu ajouté
Ligne 48 :
Voici un programme C réalisant un chenillard :
 
<sourcesyntaxhighlight lang="c">
#include "avr/io.h"
 
Ligne 67 :
}
}
</syntaxhighlight>
</source>
 
==== Partie matérielle ====
Ligne 103 :
C'est une caractéristique de ce cœur, cette facilité à transformer des registres en PORTs. Nous rappelons que ceci est fait avec le code VHDL :
 
<sourcesyntaxhighlight lang="VHDL">
-- ceci est dans un fichier io2.vhd qui remplace io.vhd original
-- IO write process
Ligne 133 :
end if;
end process;
</syntaxhighlight>
</source>
 
Et voici de manière schématique ce qu’il faut faire pour interfacer notre écran VGA au processeur :
Ligne 171 :
{{Solution|contenu=
Attachez-vous à comprendre comment le C gère les briques : comment vous savez où sont les briques ? C'est fait ici grâce aux deux tableaux tabmur1 et tabmur2 qui contiennent toutes les informations de position que vous avez dans votre partie matérielle.
<sourcesyntaxhighlight lang="c">
// gestion d'un casse brique dans un FPGA = VGA+ATMega8
// Ce programme tient dans environ {{Unité|2|{{Abréviation|ko|kilooctet}}}} sur {{Unité|8|{{Abréviation|ko|kilooctet}}}} dispo
Ligne 418 :
}
}
</syntaxhighlight>
</source>
* Cette version gère correctement 7 niveaux de jeux : après le septième niveau tout est comme au septième.
* pour le niveau 2 et 4 on est parti du principe qu’il était plus difficile de "descendre" 4 briques que 8 ce qui est faux ! à revoir donc !
Ligne 515 :
|}
Nous avons donc choisi les tout premiers registres non utilisés. Ceci est réalisé dans le fichier io2.vhd avec :
<sourcesyntaxhighlight lang="VHDL">
-- IO write process
--
Ligne 548 :
end if;
end process;
</syntaxhighlight>
</source>
 
Voila en quatre points le travail à réaliser en [[w:VHDL|VHDL]] :
Ligne 559 :
Voici le fichier io2.vhd :
{{Solution|contenu=
<sourcesyntaxhighlight lang="VHDL">
-------------------------------------------------------------------------------
--
Ligne 837 :
end Behavioral;
 
</syntaxhighlight>
</source>
}}
 
Voici le fichier VGATopCassebrique.vhd :
{{solution|contenu=
<sourcesyntaxhighlight lang="VHDL">
library ieee;
use ieee.std_logic_1164.all;
Ligne 1 390 :
end a_ligne8briques;
</syntaxhighlight>
</source>
}}
==== Partie logicielle ====
Ligne 1 396 :
 
{{Solution|contenu=
<sourcesyntaxhighlight lang="c">
// gestion d'un casse brique dans un FPGA = VGA+ATMega8
// Ce programme tient dans environ {{Unité|2|{{Abréviation|ko|kilooctet}}}} sur {{Unité|8|{{Abréviation|ko|kilooctet}}}} dispo
Ligne 1 723 :
}
}
</syntaxhighlight>
</source>
}}
 
Ligne 1 740 :
 
Si vous regardez le brochage d'un PIC24F, vous ne verrez aucune broche où apparaît "RXD" ou "TXD" : vous pouvez les mettre n’importe où. C'est pratique mais c’est une chose supplémentaire qu’il faut apprendre à gérer. Nous avons eu bien du mal à trouver un exemple. Le seul livre sur le PIC24F dont nous disposions parle de la RS232 sans évoquer ce problème ! Mais comme la platine Android de chez Microchip n'utilise pas la broche rs232 standard (du kit de développement), il faut donc réaliser sa déclaration. Ceci se fait avec le code c suivant :
<sourcesyntaxhighlight lang ="c">
#include <PPS.h> /*Pin Re-Mapping peripheral library functions */
//...................
Ligne 1 755 :
U1BRG = BRATE;
//.........................
</syntaxhighlight>
</source>
Le kit Android possède bien une E/S dédiée mais pas le composant. Si vous avez bien compris, vous voyez qu'on utilisera le port série numéro 1 (il y en a un deuxième) et que la transmission se fera sur la broche RP11.
==== Programme d'exemple pour la première UART ====
Ligne 1 765 :
* 8 bits de données
* 2 bits de stop.
<sourcesyntaxhighlight lang="C">
#include <avr/io.h>
#undef F_CPU
Ligne 1 817 :
return 0;
}
</syntaxhighlight>
</source>
La réception sans interruption peut se faire avec quelque chose comme :
<sourcesyntaxhighlight lang="c">
while (!(UCSRA & (1<<RXC))); //attente donnée RS232
PORTB = UDR;
</syntaxhighlight>
</source>
Intéressons-nous maintenant à la deuxième UART.
 
Ligne 1 829 :
 
Voici comment est faite la partie matérielle d'envoi dans le fichier io2.vhd (tous les détails ne sont pas donnés) :
<sourcesyntaxhighlight lang="VHDL">
baud: mod_m_counter
generic map (
Ligne 1 887 :
L_WE_UART2 <= I_WE_IO when (I_ADR_IO = X"24") else '0'; -- write UART2 ADCL
L_RD_UART2 <= I_RD_IO when (I_ADR_IO = X"24") else '0'; -- read UART2 ADCL
</syntaxhighlight>
</source>
L'avant dernière ligne du programme VHDL ci-dessus décide qu'une écriture dans la RS232 se fera par le registre '''ADCL''' d'adresse 0x24.
 
Ligne 1 898 :
 
Voici un exemple en C qui envoie un caractère.
<sourcesyntaxhighlight lang="c">
// Constantes
#define TXBF 4 //TXBF : buffer full en transmission
Ligne 1 950 :
return ok;
}
</syntaxhighlight>
</source>
 
Un programme principal du genre :
<sourcesyntaxhighlight lang="c">
int main(void)
{
Ligne 1 965 :
return 0;
}
</syntaxhighlight>
</source>
peut être utilisé. Ce programme insère les caractères reçus parmi les 'A' affichés dans l'hyperterminal. Les caractères envoyés ne sont pas perdus grâce au buffer de 16 caractères qui a été gardé.
=== Annexe : fichier ucf utile pour la carte Spartan3E ===
Ligne 2 031 :
Voici donc sans commentaire particulier :
* le fichier manifess.xml
<sourcesyntaxhighlight lang="xml">
<manifest package="com.pong" android:versionCode="1" android:versionName="1.0"><uses-sdk android:minSdkVersion="8" android:targetSdkVersion="11"/><uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/><uses-permission android:name="android.permission.BLUETOOTH"/><application android:icon="@drawable/ic_launcher" android:label="@string/app_name"><activity android:label="@string/app_name" android:name=".MainActivity" android:screenOrientation="portrait"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity><activity android:name=".Gyroscope"/><activity android:name=".Boutons"/></application></manifest>
</syntaxhighlight>
</source>
* le fichier MainActivity.java
{{Boîte déroulante|titre=Fichier MainActivity.java|contenu=
<sourcesyntaxhighlight lang="java">
package com.pong;
import android.app.TabActivity;
Ligne 2 069 :
}
}
</syntaxhighlight>
</source>
}}
* Le fichier Boutons.java
{{Boîte déroulante|titre=Fichier Boutons.java|contenu=
<sourcesyntaxhighlight lang="java">
package com.pong;
import android.app.*;
Ligne 2 153 :
}
}
</syntaxhighlight>
</source>
}}
* fichier Gyroscope.java
{{Boîte déroulante|titre=Fichier Gyroscope.java|contenu=
<sourcesyntaxhighlight lang="java">
package com.pong;
import android.app.*;
Ligne 2 302 :
}
}
</syntaxhighlight>
</source>
}}
 
Ligne 2 321 :
 
Comme d'habitude c’est le fichier "io2.vhd" qui est responsable de la gestion des PORTs. En voici un extrait assez significatif :
<sourcesyntaxhighlight lang="VHDL">
iowr: process(I_CLK)
begin
Ligne 2 346 :
end if;
end process;
</syntaxhighlight>
</source>
Vous avez assez de données dans cet extrait [[w:VHDL|VHDL]] pour écrire des sous-programmes demandés un peu plus loin. Si vous avez été attentif vous aurez remarqué que seuls huit bits sont utilisés pour les coordonnées alors qu'en principe 9 sont nécessaires. On a effectivement décidé de laissé tomber le bit de poids faible.
 
Ligne 2 353 :
 
Dans le projet précédent de cette même année, nous avons choisi d'interfacer la mémoire écran à travers des PORTs. C'est très facile à réaliser mais assez inefficace : rien que pour réaliser l'adresse il faut écrire dans deux PORTs. Pour mettre la donnée il faut écrire dans un autre PORT et ensuite écrire quelquefois dans le PORT de commande pour réaliser les bons signaux. Regardez pour vous convaincre comment se fait le changement du niveau (level en anglais) par écriture dans la RAM dans l'autre projet ([[w:Casse-briques|Casse-briques]]):
<sourcesyntaxhighlight lang="c">
//******************************************************************************************************************************
// function putLevel()
Ligne 2 377 :
ADCH = 0;
}
</syntaxhighlight>
</source>
Et encore on n'utilise ici qu'une adresse sur 8 bits, ce qui est impossible pour le pacman !
 
Ligne 2 394 :
 
Muni de cette expérience, nous allons prendre la partie VGA développée dans [[../../Interfaces VGA et PS2#Pacman|un autre chapitre]]. Elle contient une RAMB16_S9 pour gérer le décor (le fond d'écran) qui a été étendue en RAMB16_S9_S9, c'est-à-dire qu'on lui a ajouté une interface de lecture/écriture. Et nous allons nous arranger pour que cette deuxième interface soit reliée au cœur ATMega8. Une réussite nous permet d'envisager de changer ce que l’on veut du décor en écrivant ou lisant directement dans la RAM processeur. Fini les PORTs pour modifier le contenu de la RAM vidéo, de simples variables bien gérées suffisent. Pas convaincu ? Voici comment on change le Level dans le pacman sans aucune manipulation de PORTs :
<sourcesyntaxhighlight lang="C">
#define LEVELUNIT 1958+1024+34+900 //debut memoire(2048)+2*derniere ligne(900)+2*offset dans ligne(34)
//....
Ligne 2 412 :
*affscore = ((level &0xF0)>>4)+'0';
}
</syntaxhighlight>
</source>
Nous devons reconnaître qu’il faut manipuler le [[w:C_(langage)|language C]] avec brio pour comprendre cela. Mais l’idée générale est la suivante :
* déclarer un pointeur <pre>unsigned char *affscore;</pre>
Ligne 2 436 :
* Développer un sous-programme putScore sur le même principe.
* À partir de maintenant, amusez-vous à interfacer le joystick et votre pacman en laissant tomber enemy à l'aide de
<sourcesyntaxhighlight lang="C">
//******************************************************************************************************************************
// function setpacmanXY()
Ligne 2 450 :
PORTC=y;
}
</syntaxhighlight>
</source>
Vous ne pourrez pas aller plus loin sans savoir si vous heurtez le mur ou pas.
* Compléter le sous-programme
<sourcesyntaxhighlight lang="C">
//******************************************************************************************************************************
// function computePossibleWays()
Ligne 2 474 :
return res;
};
</syntaxhighlight>
</source>
dont l'objectif est de savoir pour toutes les positions vers quelles directions il est possible d'aller sans heurter un mur. C'est le cœur de votre travail, mais ce sous-programme est assez difficile à développer. Ce qui le rend si difficile est qu’il faut y refaire ce qui a été fait en VHDL :
# trouver le numéro de pavé à partir de x et y avec la concaténation VHDL. La difficulté et qu'ici x et y sont sur 8 bits, c'est-à-dire qu'on a perdu les deux bits de poids faibles (de pixel_x et pixel_y en VHDL). Soyez donc méthodique.
Ligne 2 480 :
# en déduire si le pavé supérieur, inférieur, droite et gauche contiennent ou non des murs (code 0xO7)
Pour vous aider nous vous donnons un sous-programme qui fait les deux premiers points :
<sourcesyntaxhighlight lang="C">
//******************************************************************************************************************************
// function computeTileAddress()
Ligne 2 503 :
return addr;
}
</syntaxhighlight>
</source>
Ce sous-programme calcule d’abord les coordonnées du centre du pacman (ou de l'ennemi) puis calcule l'adresse courante en mémoire vidéo sur laquelle on se trouve. Muni de cette adresse, il n’est pas très difficile de trouver ce qui l'entoure. Pour information nous avons testé le sous-programme complet "computePossibleWays" en manipulant l’affichage du score comme ceci :
<sourcesyntaxhighlight lang="c">
// utilisation du score pour vérifier la detection de Up Down Left Right
score=0;
Ligne 2 513 :
if (theWay & 0x01) score|=0x0001;
putScore(score);
</syntaxhighlight>
</source>
qui utilise putScore qui est la première chose que l’on vous demande de faire.
 
Ligne 2 551 :
===== La solution de l'enseignant tuteur =====
{{Boîte déroulante|titre=Solution de l'enseignant tuteur|contenu=
<sourcesyntaxhighlight lang="c">
// gestion d'un pacman dans un FPGA = VGA+ATMega8
// Serge Moutou 2012/2013
Ligne 2 948 :
while (!bit_is_set(PINB,PINB1)) ; // un coup sur droite pour débloquer
}
</syntaxhighlight>
</source>
}}
Cette version fonctionne correctement mais partiellement seulement :
Ligne 2 960 :
===== La solution des étudiants =====
{{Boîte déroulante|titre=Solution des étudiants Guillaume Demarquez et Pauline Skorupka |contenu=
<sourcesyntaxhighlight lang="c">
// ----------------------------------------------------------
// Projet TR Geii 2013 : PACMAN
Ligne 3 651 :
}
}
</syntaxhighlight>
</source>
}}
Quelques remarques sur le code :