« Very High Speed Integrated Circuit Hardware Description Language/Travail pratique/Autres projets pour ATMEL ATMega8 » : différence entre les versions
Contenu supprimé Contenu ajouté
Dépeuplement de Catégorie:Pages utilisant des balises source obsolètes |
|||
Ligne 48 :
Voici un programme C réalisant un chenillard :
<
#include "avr/io.h"
Ligne 67 :
}
}
</syntaxhighlight>
==== 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 :
<
-- ceci est dans un fichier io2.vhd qui remplace io.vhd original
-- IO write process
Ligne 133 :
end if;
end process;
</syntaxhighlight>
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.
<
// 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>
* 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 :
<
-- IO write process
--
Ligne 548 :
end if;
end process;
</syntaxhighlight>
Voila en quatre points le travail à réaliser en [[w:VHDL|VHDL]] :
Ligne 559 :
Voici le fichier io2.vhd :
{{Solution|contenu=
<
-------------------------------------------------------------------------------
--
Ligne 837 :
end Behavioral;
</syntaxhighlight>
}}
Voici le fichier VGATopCassebrique.vhd :
{{solution|contenu=
<
library ieee;
use ieee.std_logic_1164.all;
Ligne 1 390 :
end a_ligne8briques;
</syntaxhighlight>
}}
==== Partie logicielle ====
Ligne 1 396 :
{{Solution|contenu=
<
// 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>
}}
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 :
<
#include <PPS.h> /*Pin Re-Mapping peripheral library functions */
//...................
Ligne 1 755 :
U1BRG = BRATE;
//.........................
</syntaxhighlight>
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.
<
#include <avr/io.h>
#undef F_CPU
Ligne 1 817 :
return 0;
}
</syntaxhighlight>
La réception sans interruption peut se faire avec quelque chose comme :
<
while (!(UCSRA & (1<<RXC))); //attente donnée RS232
PORTB = UDR;
</syntaxhighlight>
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) :
<
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>
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.
<
// Constantes
#define TXBF 4 //TXBF : buffer full en transmission
Ligne 1 950 :
return ok;
}
</syntaxhighlight>
Un programme principal du genre :
<
int main(void)
{
Ligne 1 965 :
return 0;
}
</syntaxhighlight>
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
<
<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>
* le fichier MainActivity.java
{{Boîte déroulante|titre=Fichier MainActivity.java|contenu=
<
package com.pong;
import android.app.TabActivity;
Ligne 2 069 :
}
}
</syntaxhighlight>
}}
* Le fichier Boutons.java
{{Boîte déroulante|titre=Fichier Boutons.java|contenu=
<
package com.pong;
import android.app.*;
Ligne 2 153 :
}
}
</syntaxhighlight>
}}
* fichier Gyroscope.java
{{Boîte déroulante|titre=Fichier Gyroscope.java|contenu=
<
package com.pong;
import android.app.*;
Ligne 2 302 :
}
}
</syntaxhighlight>
}}
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 :
<
iowr: process(I_CLK)
begin
Ligne 2 346 :
end if;
end process;
</syntaxhighlight>
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]]):
<
//******************************************************************************************************************************
// function putLevel()
Ligne 2 377 :
ADCH = 0;
}
</syntaxhighlight>
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 :
<
#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>
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
<
//******************************************************************************************************************************
// function setpacmanXY()
Ligne 2 450 :
PORTC=y;
}
</syntaxhighlight>
Vous ne pourrez pas aller plus loin sans savoir si vous heurtez le mur ou pas.
* Compléter le sous-programme
<
//******************************************************************************************************************************
// function computePossibleWays()
Ligne 2 474 :
return res;
};
</syntaxhighlight>
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 :
<
//******************************************************************************************************************************
// function computeTileAddress()
Ligne 2 503 :
return addr;
}
</syntaxhighlight>
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 :
<
// 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>
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=
<
// 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>
}}
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=
<
// ----------------------------------------------------------
// Projet TR Geii 2013 : PACMAN
Ligne 3 651 :
}
}
</syntaxhighlight>
}}
Quelques remarques sur le code :
|