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.
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.
Copyright Squale92 & Verstand. Logo et sigle TCI® réservés. Développé pour MS Internet Explorer 5.0 en 1024x768 pixels. Page modifiée le