Salut tout le monde,
Le problème principal venait de moi, donc mea-culpa. Et il n'était pas de 8 cycles (mauvaise interprétation de ma part puisque j'y voyais un pb spécifique au 6846) mais d'un nombre plutôt variable de cycles dépendant de l'instruction exécutée avant le traitement du timer. C'est donc spécifique à mon émulateur.
Une fois mon problème fixé, j'ai établi quelques benchs sur mon vrai To9 avec des relevés de compteur. Et à force de tâtonner, j'ai fini par comprendre comment faire les choses sans faire de rustine. Ceci dit, j'ai pas encore fait le tour de tous les cas. Je dois encore faire d'autres benchs sur mon To9 dès que j'y aurai accès.
Je livre ici mon histoire, c'est-à-dire ce que j'ai appris mais que vous savez peut-être déjà ou pas. Au moins, ça laisse une trace écrite pour ceux qui chercheraient:
- Comme @gilles l'a écrit, pour bien compter, il faut savoir quand relever les cycles pour agir sur le timer. Donc, pour chaque instruction LD, ST, PSH, ADD, etc., il faut prendre un cycle par accès bus, en fin d'instruction (façon de parler). En clair, si on fait un 'LDA $e7c6', le registre du timer, est lu 1 cycle avant la fin de l'instruction. Dans le cas d'un 'LDD $e7c6', '$e7c6' est lue 2 cycles avant la fin de l'instruction. Et '$e7c7' est lue un cycle avant la fin. Idem dans le cas d'un STA ou un STD. Donc, j'ai modifié mes instructions de lecture/écriture en conséquence.
- Comme c'est marqué dans la doc, le timer utilise un registre temporaire pour bien fonctionner sur un proc 8 bits. Quand on fait un 'STD $e7c6', le 6809 écrit la donnée en big endian. Le timer mets d'abord la valeur d'$e7c6 dans un registre temporaire, et attend la donnée d'$e7c7 pour recomposer la valeur d'initialisation du timer avec le registre temporaire. C'est l'écriture dans $e7c7 qui change la valeur du latch. Et c'est donc l'écriture dans cette adresse qui peut enclencher la réinitialisation du timer. L'écriture dans $e7c6 ne produit aucune action sur le timer.
- A l'inverse, quand on fait un 'LDD $e7c6', il faut savoir que le timer fait un relevé de compteur à la lecture d'$e7c6. Et il stock le poids fort qui sera donné par $e7c7, dans un registre temporaire (probablement le même que pour l'écriture mais je dois faire un test sur mon to9 pour le vérifier). De cette manière, quand le 6809 lit $e7c7 juste après, le relevé est cohérent. En effet, imaginons que le décompteur soit à $0100 au moment de la lecture d'$e7c6 via un LDD; un cycle se passe et la valeur passe virtuellement à $00ff; le 6809 lit ensuite $e7c7 et prend la valeur $ff; au final, on aurait $01ff dans le registre 'D'. D'où l'utilité du registre temporaire. J'ai fait le test et, APRES avoir lu $e7c6, c'est toujours la même valeur que l'on lit dans $e7c7. C'est bien la lecture d'$e7c6 qui enclenche l'initialisation d'$e7c7. (La plupart des émulateurs se gourre ici)
Je me suis penché ensuite sur la problématique du décomptage 1 millionième/1 huitième et comment ce flag était pris en compte (bit3 d'$e7c5).
Après beaucoup de tests, la solution était simple. Ce flag est pris en compte au moment de l'écriture en $e7c7 (mais j'ai encore des conditions à vérifier dans ce cas). Il est également pris en compte quand le décompteur est en fonctionnement et que l'on change le flag d'$e7c5 tout en gardant le bit0 à 0. En revanche, il n'est pas pris en compte quand vous allumez le décomptage (bit0 à 0) alors que le décompteur était à l'arrêt juste avant (bit0 à 1).
J'ai appris enfin un truc que je ne savais pas: on peut changer la valeur d'initialisation du timer pendant un décomptage. Par contre, il y a des conditions. J'ai implémenté les choses comme dans le code de MESS mais j'attends de faire des tests sur mon To9, pour faire le tour du sujet. A moins que quelqu'un d'autre ici s'en charge...
Voilà pour le moment. J'espère que c'est au moins clair, sinon instructif pour vous.
a+
|