|
L'équipe progG de Ti-Fr
|
Voici les nicks de vos serviteurs ;-)
chickensaver_john
Kevin Kofler
Thibaut
janjan2
TiMad
Iceman89
fréka
Zewoo
Squale92
Verstand
ZdRUbAl
UtOpIaH
et nEUrOne ...
|
|
Une idée ?
|
Une idée pour améliorez cette partie?
ou tout simplement vous souhaitez participer à l'élaborations
des tutos.
Mailez-nous ici
|
| |
Chapitre
VI (version 89)
Tout d'abord, je vais vous demander de m'excuser pour ne
pas avoir suivi un raisonnement très logique. En effet, j'ai écrit ce chapitre
en deux versions : une pour TI-89, et l'autre pour TI-92plus.
Cela est du au fait que, dans ce chapitre, nous allons partir de l'exemple d'un
programme qui utilise des fonctions graphiques. Étant donné que les écrans de
ces deux calculatrices sont de tailles très différentes, j'ai préféré
dédier une page à chacune d'entre elles, ce qui simplifiera fortement la
compréhension : vous n'aurez ici pas de valeurs n'ayant aucun rapport avec une
TI-89 !
Dans ce chapitre, nous allons partir de l'exemple d'un
programme sans grande utilité, mais assez simple, qui nous permettra de
découvrir de nouvelles fonctions (en une quantité qui ne sera pas trop
importante !) sans ramener une trop grande quantité de celles apprises
précédemment (On supposera qu'elles sont acquises pour la suite !).
Pour vous donner une idée du résultat que
donnera ce programme, nous allons commencer par regarder quelques copies
d'écran (réalisées grâce à VTI !) :

Elles ont toutes deux été réalisées pendant l'exécution du programme !
I:\ Explications
préliminaires :
A: Nous avons
déjà appris à définir une macro en utilisant #define
.... Nous n'avions utilisé cette instruction que pour donner un
exemple de ce qu'elle permettait. Maintenant, nous allons utiliser une autre
technique pour faire (en gros !) la même chose, mais cette technique est celle
que vous rencontrerez le plus souvent, et c'est aussi (à mon avis !) celle que
vous préférerez, de par sa plus grande clarté en particulier.
Nous avons dis que, pour définir la fonction _main, il
fallait utiliser ...(Quelle instruction au fait ???) ce que nous faisons
toujours, c'est à dire :
void
_main(void)
{
Instructions de la
fonction.
}
Eh bien, pour les autres fonctions que nous voudront
définir pour un programme, nous utiliserons exactement la même chose. Ainsi,
dans le cas d'une fonction qui ne demande pas d'arguments, et qui ne renvoie pas
de résultat, on aura (en supposant que cette fonction se nomme "wait")
:
void
wait(void)
{
Instructions de la
fonction wait
}
...
void
_main(void)
{
Instructions de la
fonction _main
wait();
Suite des instructions de
_main
}
Il est ainsi possible de définir des fonctions de tous
types, qui pourront alors être utilisées comme les fonctions de base inclues
dans les librairies de TIGCC.
B: Les
Timers de la calculatrice :
Nos TI contiennent six Timers. Voir le fichier <System.h>
de l'aide de TIGCC pour plus de précisions sur ceux-ci en général. Ici, nous
allons utiliser le Timer n°6, défini de façon générale comme USER_TIMER.
C'est un Timer qu'il nous est possible d'utiliser comme nous le souhaitons, sans
danger pour la TI. (D'après la doc de TIGCC, et d'après ma propre expérience
!). Pour pouvoir "imposer" nos propres valeurs aux Timers de la TI, il
faut "dire" à la TI que nous allons le faire. Pour cela, il faut
utiliser l'instruction :
OSFreeTimer(timer_n°X);
Dans notre cas, nous aurons donc, pour
"libérer" le Timer USER_TIMER
:
OSFreeTimer(USER_TIMER);
Pour affecter la valeur que nous souhaitons au Timer que
nous avons "libéré" au préalable, il faut utiliser l'instruction :
OSRegisterTimer(timer_n°X, Valeur*20);
timer_n°X correspond au nom du Timer en
question, et Valeur correspond à la valeur que nous voulons lui
affecter. Cette valeur doit être multipliée par 20 (opération Valeur*20),
car la "minuterie" qui règle les Timers est sollicitée 20 fois par
seconde.
Pour le Timer de notre exemple, si
nous voulons qu'il ait pour valeur 3 secondes, il faudra donc faire :
OSRegisterTimer(USER_TIMER, 3*20);
Pour vous entraîner un peu, je vais vous proposer un
exercice tout simple : vous savez sans doute qu'il est possible de régler la
valeur de l'APD (Auto Power Down, temps qu bout duquel la TI s'éteint toute
seule.) à partir de programmes comme Doors-Explorer. Ce que je vous propose,
c'est de créer un programme qui change cette valeur, en la fixant, par exemple,
à 100 secondes. Pour cela, je vais vous donner une indication : le nom du Timer
qui est utilisé pour l'APD est APD_TIMER.
La solution est la suivante :
Les lignes de code qui permettent de
changer l'APD sont :
OSFreeTimer(APD_TIMER);
OSRegisterTimer(APD_TIMER, 100*20);
Naturellement, il faut
insérer ces lignes de code dans un programme
Enfin, nous allons voir la dernière fonction
concernant les Timers que nous utiliserons dans ce Chapitre : il peut être
utile de savoir quand un la valeur d'un Timer est passée. (C'est ainsi que,
quand tout le temps du Timer de l'APD s'est écoulé, la TI s'éteint !). Pour
cela, on utilise la fonction :
OSTimerExpired(timer_n°X);
Cette fonction renvoie TRUE
si le Timer est arrivé à la fin de son compte à rebours, et retourne FALSE
tant que ce n'est pas le cas. Ici, il s'agira, pour notre Timer, de :
OSTimerExpired(USER_TIMER);
Voilà, à présent vous connaissez les instructions de
base concernant les Timers de votre TI. Pour en savoir plus, je vous encourage
à aller lire la doc de TIGCC (<System.h>), ou alors, peut-être un jour
sera-t-il possible de trouver un chapitre dans ce tutorial qui ne soit consacré
qu'aux Timers. Peut-être...
C: Les
boucles de répétition de type for :
Pour pouvoir utiliser ce type de boucles, il faut déjà que
vous ayez une variable de type short. (Dans
les versions de TIGCC antérieures à la 0.9, il fallait utiliser int
!). Dans notre exemple, nous prendrons la variable nommée i. Ensuite, il
faut utiliser la syntaxe générale :
for
(i=valeur_de_départ; condition; incrémentation)
{
Instructions à
effectuer.
}
La valeur de départ est celle que vous donnerez à i
au début de la boucle for. Cette valeur
sera augmenté (ou diminuée !) de incrémentation, jusqu'à ce que la condition
devienne fausse. Pour vous donner une petite idée, vous pouvez construire une
boucle for qui exécutera 100 fois certaines instructions.
La solution est la suivante :
for
(i=0; i<100; i++)
{
Instructions à
effectuer.
}
Remarque : Ici, nous avons utilisé une
variable de type short
comme compteur, mais il est possible d'utiliser d'autres type de variables numériques,
telles les longs...
D: Instructions
graphiques utilisées ici :
Nous allons utiliser deux instructions graphiques simples
dans l'exemple que nous allons prendre ici. La première permet de dessiner des
lignes à l'écran, et la seconde permet de tracer des ellipses, et donc des
cercles (Un cercle est une ellipse de forme particulière !)
L'instruction que nous allons utiliser pour tracer des
lignes sur l'écran de notre TI est simple. Sa syntaxe générale est de la
forme :
DrawLine(x0, y0, x1, x2, Attribut);
Ici, x0, x1, y0 et y2 sont
des valeurs de type short . Il s'agit des
cordonnes du point de départ, suivies de celle du point d'arrivée.
L'Attribut permet de dire comment sera dessinée la
ligne. Les plus utilisés sont A_NORMAL
(dessine une ligne normal), A_REVERSE
(efface un ligne) et A_XOR (dessine une
ligne en XOR, c'est-à-dire en OU exclusif; comme le fait l'attribut -1 pour la
fonction PxlLine en TI-BASIC).
Pour les autres, je vous invite à aller consulter la doc de TIGCC.
L'instruction que nous allons utiliser pour tracer des
cercles sur notre écran est un peu moins simple, mais elle reste facilement
compréhensible. Sa syntaxe générale est :
DrawClipEllipse(x, y, a, b, SCR_RECT *clip, Attribut);
Ici, x, y, a et b sont des
valeurs de type short. x et y
désignent les coordonnées du centre de l'ellipse, et a et b
désignent les longueurs des demi-axes de celle-ci. Ainsi, si on pose a=b,
on aura un cercle. (C'est ce que nous allons utiliser dans le programme qui sert
ici d'exemple !).
L'Attribut permet ici aussi de dire comment sera
dessinée l'ellipse. Pour cette instruction, il n'existe que trois attributs,
qui sont ceux donnés ci-dessus pour la fonction DrawLine.
La constante SCR_RECT *clip permet de définir dans
quelle partie de l'écran nous allons utiliser cette fonction. Ici, pour
simplifier, nous avons choisi d'utiliser l'écran entier, et ce dans tous les
cas. Pour cela, on place ceci :
&(SCR_RECT){{0, 0, 160, 100}} à la place de SCR_RECT *clip.
II:\ le code source,
pour TI-89 :
#define
OPTIMIZE_ROM_CALLS
#define SAVE_SCREEN
#include <tigcclib.h> >
short _ti89;
void wait(void)
{
OSFreeTimer(USER_TIMER);
OSRegisterTimer(USER_TIMER,
20);
while(!OSTimerExpired(USER_TIMER));
}
void _main(void)
{
short
i=0;
clrscr();
for (i=0
; i<100
; i++)
{
DrawLine(0,
0, 159,
100-i,
A_XOR);
DrawLine(159,
0, 0,
100-i,
A_XOR);
DrawLine(0,
100, 159,
i, A_XOR);
DrawLine(159,
100, 0,
i, A_XOR);
}
wait();
for (i=0
; i<80
; i++)
{
DrawLine(i,
0, i,
100, A_XOR);
DrawLine(159-i,
0, 159-i,
100, A_XOR);
}
wait();
for (i=0
; i<80
; i++)
{
DrawLine(i,
0, i,
100, A_REVERSE);
DrawLine(159-i,
0, 159-i,
100, A_REVERSE);
}
wait();
for (i=0
; i<80
; i++)
{
DrawLine(i,
0, i,
100, A_NORMAL);
DrawLine(159-i,
0, 159-i,
100, A_NORMAL);
}
wait();
for (i=0
; i<80
; i=i+2)
{
DrawClipEllipse(80,
50, i,
i, &(SCR_RECT){{0,
0, 159,
100}}, A_XOR);
}
wait();
for (i=0
; i<51
; i++)
{
DrawClipEllipse(0,
50, i,
i, &(SCR_RECT){{0,
0, 160,
100}},A_XOR);
DrawClipEllipse(160,
50, i,
i, &(SCR_RECT){{0,
0, 160,
100}},A_XOR);
DrawClipEllipse(80,
0, i,
i, &(SCR_RECT){{0,
0, 160,
100}}, A_XOR);
DrawClipEllipse(80,
100, i,
i, &(SCR_RECT){{0,
0, 160,
100}},
A_XOR);
DrawClipEllipse(80,
50, i,
i, &(SCR_RECT){{0,
0, 160,
100}}, A_XOR);
}
wait();
for (i=0
; i<50
; i++)
{
DrawClipEllipse(80,
50, i,
i, &(SCR_RECT){{0,
0, 159,
100}}, A_XOR);
}
wait();
for (i=0
; i<11
; i++)
{
DrawClipEllipse(80,50,
i, i, &(SCR_RECT){{0,
0, 159,
100}},
A_NORMAL);
}
wait();
wait();
}
III:\ Comparaison
entre C et TI-BASIC :
Test effectué sur une
TI-92plus, et pas sur une TI-89. Il est donc possible que les valeurs ne soient
pas tout à fait identique sur cette calculatrice !
Pour avoir une petite idée des capacités du C par
rapport à celles du TI-BASIC, j'ai fait un petit test : j'ai écrit
l'équivalent de ce programme en TI-BASIC, et, ensuite, j'ai
chronométré combien de temps il fallait à chaque version pour s'exécuter.
Les valeurs que je présente ici ne sont pas très précises, car elles
dépendent de l'état des piles de la TI qui a servit.
- Pour la version C, il faut environ 22 secondes pour l'exécution du
programme (Avec les boucles d'attentes de une seconde !!!), et il occupe 743
octets de mémoire.
- Pour la version en TI-BASIC, il faut environ 1minunte et 10
secondes pour l'exécution du programme (Avec des boucles de type
for...endfor, de valeur de 0 à 250, et il occupe 652 octets de mémoire.
On peut donc dire que le programme en C est trois
fois plus rapide que son équivalent TI-BASIC, et, surtout, il permet
de disposer de TOUT l'écran. (Alors que le programme en TI-BASIC
nous force à garder la barre de menus en haut de l'écran, ainsi que la Status
Line !)
Il faut de tout de même savoir que la vitesse du programme
en C par rapport à celle du programme en TI-BASIC dépend des instructions
C utilisées ; ainsi, si vous utilisez un grand nombre d'instructions
du fichier <bascmd.h>, la vitesse se trouvera fortement ralentie, puisque
ces instructions ne sont rien d'autre que des appels à des instructions de type
TI-BASIC.
Retour au menu général
Chapitre
VII
|
|