Seuls les membres ayant 30 points peuvent parler sur le chat.

Forum Casio - Discussions


Index du Forum » Discussions » Le KEYSC / gestion du clavier
Yatis En ligne Membre Points: 492 Défis: 0 Message

Le KEYSC / gestion du clavier

Posté le 09/09/2018 21:59

En essayant de comprendre comment key_down() fonctionnait je suis tombé sur ce bout de code:

memcpy(&key, keyboardregister, sizeof(unsigned short) << 3);
row= code%10;
return (0 != (key[row >> 1] & 1 << code / 10 - 1 + ((row & 1) << 3)));


Je n'ai pas compris pourquoi on fait un memcpy() et ni pourquoi on "précalcule" row à l'avance, bref j'ai écrit ça:

return (0 != (keyboardregister[(code % 10) >> 1] & 1 << code / 10 - 1 + (((code % 10) & 1) << 3)));


ça fonctionne tout aussi bien.
Je me suis donc empressé de demander l'intérêt de faire un memcpy() alors que tout peut tenir sur une ligne.
Lephenixnoir m'a expliqué que c'est moche et niveau maintenabilités ce n'est pas terrible.
Il a ajouté que le mieux serais de regarder au niveau du KEYSC.
(D'ailleurs voila le résumer de ce que sait Lephe' sur le KEYSC http://www.casiopeia.net/forum/viewtopic.php?f=25&t=7329)

Du coup j'ai quelque petite question à propos du KEYSC.
-En quoi utiliser KEYSC est moins "crado" que ma magnifique ligne ?
-Quelle est la différence entre 0xA44B0000 (keyboard register) et le KEYSC ?
-As-tu déassembler le syscall 0x117 ? (c'est celui qui initialise le KEYSC (?))
-Arrive-t-il à échapper au problème de "shadowing" (SHIFT + REPLAY) ?
-Gint arrive-t-il à utiliser le KEYSC ?
-Du coup, dans l'idéal il faudrait arrivera une méthode proche de celle des sh3 (mais là avec les portes Z, M, N) ?


Lephenixnoir En ligne Administrateur Points: 17460 Défis: 142 Message

Citer : Posté le 10/09/2018 07:06 | #


Pourquoi précalculer row à l'avance ? Au cas où tu ne le sais pas, calculer une division ou un modulo sur cette architecture prend environ 70 cycles, soit bien 4 ou 5 fois plus que le reste de la fonction. Tous les moyens sont bons pour que le vieux compilo de Renesas n'essaie pas de le calculer en plus deux fois.

Voilà comment j'aurais personnellement écrit la fonction...

int key_down(int keycode)
{
  volatile uint16_t *KEYSC = (void *)0xa44b0000;
  int row = code % 10;
  int col = code / 10 - 1;
  int mask = col | ((row & 1) << 3);

  return (KEYSC[row >> 1] & mask) != 0;
}

C'est le même code que toi, mais...
- J'ai explicité qu'il y avait une ligne et une colonne, le lecteur comprend comment keycode est constitué
- J'ai fait apparaître row & 1 et row >> 1 pour montrer que le dernier bit est utilisé différemment (8 bits par ligne mais 16 bits par accès tableau, il faut ajuster)
- Toi, quand tu tombes là-dessus tu comprends sans doute mieux que le code originel.

Et le compilateur sait compiler, il sortira le même code en sortie. Il sait inliner les variables intermédiaires...

Le KEYSC, c'est exactement ça. Tu as vu cette fonction, tu as vu le KEYSC. L'autre alternative c'est lire les ports directement, mais ça a aussi ses inconvénients.

Pour les questions :

- Ta ligne utilise le KEYSC mais le code est terrible. C'est comme si tu avais compilé toi-même pour supprimer le sens de ce que tu calcules et le remplacer par une formule brute. Laisse le compilo compiler, ce dont ton lecteur a besoin c'est de comprendre ce qui se passe.
- Aucune, sous SH7305 le KEYSC sembler comporter comme seuls registres les 6 différentes entrées de ce tableau.
- Pas encore, mais j'ai envisagé de le faire hier.
- Non, le shadowing est impossible à contourner, c'est un problème électronique.
- Oui, mais il y a quelques subtilités, donc je contourne un peu pour arriver à mes fins. C'est encore en phase de test.
- Pas forcément, car quand tu lis les ports tu dois faire des petites attentes entre les actions avec les ports et ce délai est crucial. S'il est trop faible, tu ne liras rien du tout. S'il est trop long, tu vas avoir du shadowing entre toutes les touches. Et la vitesse d'attente dépend évidemment de l'overclock, donc il faut ajuster le délai quand on overclocke. Sous SH3 il y a le watchdog qui permet de faire ça assez bien, sous SH4 il n'y a rien, et on n'a pas envie d'utiliser un timer à la place. Les anciennes versions de gint freezent sous overclock car le délai du clavier n'est plus respecté et il ne lit plus rien du tout.
Yatis En ligne Membre Points: 492 Défis: 0 Message

Citer : Posté le 10/09/2018 09:52 | #


Lephenixnoir a écrit :

Pourquoi précalculer row à l'avance ? Au cas où tu ne le sais pas, calculer une division ou un modulo sur cette architecture prend environ 70 cycles, soit bien 4 ou 5 fois plus que le reste de la fonction. Tous les moyens sont bons pour que le vieux compilo de Renesas n'essaie pas de le calculer en plus deux fois.

Je sais très bien que le modulo est une opération longue et qu'il n'est pas envisageable de l'effectuer 2 fois.
Tu te doutes bien que si j'ai pris le risque de dire que ma ligne est exactement pareil que le code de base, c'est que j'ai vérifié ce que le compilo a fait... MAIS j'avais oublié que:
Lephenixnoir a écrit :

Et le compilateur sait compiler, il sortira le même code en sortie. Il sait inliner les variables intermédiaires...

Hé hop, j'ai changer la ligne dégueulasse, on a rien vu xD
Mais sinon tu a raison c'est illisible au possible et ça revient au même que ton code ('fin bon je reste convaincu que le memcpy() est inutile dans usefull.h).

Lephenixnoir a écrit :

Le KEYSC, c'est exactement ça. Tu as vu cette fonction, tu as vu le KEYSC. L'autre alternative c'est lire les ports directement, mais ça a aussi ses inconvénients.

Oui mais ça permettrait d'avoir le même code pour sh3 que pour sh4...
TeamFX a écrit :

Ports (SH-4A):
PTZ(7:0) : col 0..7
PTM(5:0) : row 0..5
PTN(5:0) : row 6..B

Ports (SH-3):
PTA(7:0) : col 0..7
PTB(7:0) : row 0..7
PTM(3:0) : row 8..B

Refer to page "fx legacy schematics" in Simon's documentation

Ha bah nan

Lephenixnoir a écrit :

Pas forcément, car quand tu lis les ports tu dois faire des petites attentes entre les actions avec les ports et ce délai est crucial. S'il est trop faible, tu ne liras rien du tout. S'il est trop long, tu vas avoir du shadowing entre toutes les touches. Et la vitesse d'attente dépend évidemment de l'overclock, donc il faut ajuster le délai quand on overclocke. Sous SH3 il y a le watchdog qui permet de faire ça assez bien, sous SH4 il n'y a rien, et on n'a pas envie d'utiliser un timer à la place. Les anciennes versions de gint freezent sous overclock car le délai du clavier n'est plus respecté et il ne lit plus rien du tout.

Mmmmmm le code utilisé pour les sh3 (key_down()) pour attendre est juste une boucle (qui boucle dans le vide) donc il n'est pas bon si jamais on overclock trop...
Et c'est sure que sous sh4 le watchdog n'est pas présent ? o_O
(D'ailleurs si j'ai bien compris le WDT suis un timer qui se règle sous la fréquence actuelle du processeur ?)
Mais du coup Getkey() aussi doit avoir un dépendance avec la fréquence ? (à moins qu'il n'utilise pas le KEYSC et dans ce cas-là j'aimerais bien savoir comment il fonctionne, du moins ce qu'il utilise pour la gestion du clavier)
Lephenixnoir En ligne Administrateur Points: 17460 Défis: 142 Message

Citer : Posté le 10/09/2018 16:35 | #


('fin bon je reste convaincu que le memcpy() est inutile dans usefull.h).

En principe oui, mais le raisonnement derrière n'est pas dénué de sens. Ce n'est pas de la mémoire normale, c'est un dialogue avec un périphérique. Si ça se trouve, chaque accès à ce tableau génére une opération d'I/O sur les ports (oh !). Souvent tu as envie de contrôler la fréquence de ces I/O, en cachant les valeurs via memcpy(), pour ne pas surcharger le matêriel (car souvent le processeur va bien plus vite). Ou alors ces I/O sont lentes donc tu peux vouloir cacher pour la performance...

Oui mais ça permettrait d'avoir le même code pour sh3 que pour sh4...

Entre écrire un deuxième driver, et réutiliser le même avec des ports différents au risque de devoir monopoliser un timer pour ne pas exploser en situation d'overclock, mon choix est vite fait.

Mmmmmm le code utilisé pour les sh3 (key_down()) pour attendre est juste une boucle (qui boucle dans le vide) donc il n'est pas bon si jamais on overclock trop...
Et c'est sure que sous sh4 le watchdog n'est pas présent ? o_O
(D'ailleurs si j'ai bien compris le WDT suis un timer qui se règle sous la fréquence actuelle du processeur ?)
Mais du coup Getkey() aussi doit avoir un dépendance avec la fréquence ? (à moins qu'il n'utilise pas le KEYSC et dans ce cas-là j'aimerais bien savoir comment il fonctionne, du moins ce qu'il utilise pour la gestion du clavier)

Je pense que CheckKeyRow() est possiblement instable sous overclock en effet ; après SimLo l'a écrite poir SH3 et les SH3 se comportent bien en général. Le même délai sous SH4 explose par contre.

Le watchdog, en principe, c'est un timer qui reset la machine s'il arrive à 0. C'est utilisé pour auto-corriger des pannes ; en temps normal le système le redémarre très régulièrement mais s'il tombe en panne il ne pourra pas l'arrêter et se fera redémarrer, ce qui donne une chance de corriger automatiquement le problème. C'est essentiel pour envoyer des robots sur Mars mais inutile pour la calculatrice.

Maintenant le WDT de la SH3 a une autre fonction timer classique (qui compte sur Pphi, aucun rapport avec "compter à la frèquence du proco Iphi" AFAIK) utilisée par le driver clavier dans le syscall 0x24a, que j'ai désassemblé. Le WDT de la SH4 n'a que la fonction de reset auto et ne peut pas être utilisé pour le clavier.

Je n'ai jamais désassemblé GetKey() (probablement très lourd et très compliqué), mais quoi que tu aies en tête, il n'est pas supposé dépendre d'un délai quelconque. Si tu peux préciser je pourrai être plus explicite. Quant aux accès clavier, il s'appuie certainement sur d'autres syscalls plus bas niveau comme 0x24a, celui-là spécifiquement utilisant aussi le KEYSC.
Yatis En ligne Membre Points: 492 Défis: 0 Message

Citer : Posté le 12/09/2018 14:04 | #


Lephenixnoir a écrit :

En principe oui, mais le raisonnement derrière n'est pas dénué de sens. Ce n'est pas de la mémoire normale, c'est un dialogue avec un périphérique. Si ça se trouve, chaque accès à ce tableau génére une opération d'I/O sur les ports (oh !). Souvent tu as envie de contrôler la fréquence de ces I/O, en cachant les valeurs via memcpy(), pour ne pas surcharger le matêriel (car souvent le processeur va bien plus vite). Ou alors ces I/O sont lentes donc tu peux vouloir cacher pour la performance...

Je ne fais qu'une seule entrée dans le KEYSC alors que memcpy() doit copier tout le tableau donc lui aussi au minimum doit entrer une fois dans le périphérique non ? (Je dois avouer n'avoir aucune connaissance sur le comment memcpy() fonctionne).

Lephenixnoir a écrit :

Entre écrire un deuxième driver, et réutiliser le même avec des ports différents au risque de devoir monopoliser un timer pour ne pas exploser en situation d'overclock, mon choix est vite fait.

J'imagine bien, seulement je vois toujours par l'intérêt de passer par autre chose que le KEYSC, à moins que ce dernier freeze en cas d’overclock (et dans ce cas la je comprends pourquoi tu veux réécrire un driver).

Lephenixnoir a écrit :

Maintenant le WDT de la SH3 a une autre fonction timer classique (qui compte sur Pphi, aucun rapport avec "compter à la frèquence du proco Iphi" AFAIK) utilisée par le driver clavier dans le syscall 0x24a, que j'ai désassemblé. Le WDT de la SH4 n'a que la fonction de reset auto et ne peut pas être utilisé pour le clavier.

Ha donc le driver clavier SH4 utilisé par le syscall 0x24a fonctionne comment s'il ne s'appuie pas sur le WDT ? il utilise le timer 0 ? (je dis "timer 0" parce qu'il m'arrivais de ne pas réussir à setuper TCR_0 pour aucune raison...mais je pense que c'est Getkey() qui le setup comme il le veut sans demander d'avis a personne (ou alors c'est le driver clavier qui est le fautif (ou moi xD))).

Lephenixnoir a écrit :

Je n'ai jamais désassemblé GetKey() (probablement très lourd et très compliqué), mais quoi que tu aies en tête, il n'est pas supposé dépendre d'un délai quelconque. Si tu peux préciser je pourrai être plus explicite. Quant aux accès clavier, il s'appuie certainement sur d'autres syscalls plus bas niveau comme 0x24a, celui-là spécifiquement utilisant aussi le KEYSC

GetKey() gère bien les touches ? Je pensais qu'il utilisait son propre driver clavier (a cause de la touche MENU et SHIFT + AC/ON).Je serais curieux de savoir comment la touche MENU fonctionne (cette question s'éloigne un petit peut du sujet mais pas trop).Comment tu t'y es pris pour que la touche MENU (dans gint) "fonctionne" comme GetKey() ?
Mais sinon pour résumer, ma question principale est: comment aimerais-tu gérer le clavier ? et en quoi KEYSC ne te convient "pas assez" ?
Lephenixnoir En ligne Administrateur Points: 17460 Défis: 142 Message

Citer : Posté le 12/09/2018 18:27 | #


Yatis a écrit :
Je ne fais qu'une seule entrée dans le KEYSC alors que memcpy() doit copier tout le tableau donc lui aussi au minimum doit entrer une fois dans le périphérique non ? (Je dois avouer n'avoir aucune connaissance sur le comment memcpy() fonctionne).

Comme je l'ai dit, une fonction élaborée peut faire un memcpy() de temps en temps et pas d'accès le reste du temps. Ce n'est pas le cas ici. Je ne disais pas que la fonction originelle était mieux ; seulement que l'idée de copier toutes les données avant de les lire a du sens.

J'imagine bien, seulement je vois toujours par l'intérêt de passer par autre chose que le KEYSC, à moins que ce dernier freeze en cas d’overclock (et dans ce cas la je comprends pourquoi tu veux réécrire un driver).

Tu n'as pas l'air très au point.
- Sur SH3, on peut faire l'I/O uniquement par les ports.
- Sur SH4, on peut faire l'I/O par les ports ou utiliser le KEYSC.

Ici donc, écrire un nouveau driver et utiliser le KEYSC sont la même option. L'idée que je rejette c'est d'accéder directement aux ports de la SH4, comme on fait sur SH3, parce que je trouve les délais trop difficiles à gérer. C'est les ports qui cassent sous overclock. Le KEYSC supporte très bien l'overclock, en fait il aime ça on dirait.

Ha donc le driver clavier SH4 utilisé par le syscall 0x24a fonctionne comment s'il ne s'appuie pas sur le WDT ? il utilise le timer 0 ? (je dis "timer 0" parce qu'il m'arrivais de ne pas réussir à setuper TCR_0 pour aucune raison...mais je pense que c'est Getkey() qui le setup comme il le veut sans demander d'avis a personne (ou alors c'est le driver clavier qui est le fautif (ou moi xD))).

Non, le driver SH4 utilise le KEYSC qui fait sa propre tambouille électronique en interne et dans notre dos. Ça marche, on ne sait pas comment, et ça nous plaît. Si tu n'arrives pas à setup TCR0 vérifie ton code, ce n'est pas ça. GetKey() n'est pas responsable, le système n'utilise jamais TCR0 AFAIK.

GetKey() gère bien les touches ? Je pensais qu'il utilisait son propre driver clavier (a cause de la touche MENU et SHIFT + AC/ON).Je serais curieux de savoir comment la touche MENU fonctionne (cette question s'éloigne un petit peut du sujet mais pas trop).Comment tu t'y es pris pour que la touche MENU (dans gint) "fonctionne" comme GetKey() ?
Mais sinon pour résumer, ma question principale est: comment aimerais-tu gérer le clavier ? et en quoi KEYSC ne te convient "pas assez" ?

GetKey() gère bien MENU tout comme SHIFT+OPTN pour le rétroéclairage. Mais ce n'est pas lui qui va lire le clavier, ce sont les sycalls du driver. Le fonctionnement de la touche MENU est compliqué au niveau du système, je ne connais pas les détails mais je ne suis pas sûr que ce soit facile à attaquer.

Dans gint, quand on appuie sur MENU je coupe gint, je restaure toute la configuration du système, j'injecte MENU dans le key buffer et j'invoque GetKey(). Tu vois, mieux vaut ne pas chercher dans le détail comment ça marche.

Enfin, tu as inversé les thèses : le KEYSC me va très bien. Utiliser les ports ne me plaît pas car je ne sais pas comment gérer correctement les attentes entre toutes les opérations sur les ports.
Yatis En ligne Membre Points: 492 Défis: 0 Message

Citer : Posté le 04/02/2019 11:35 | #


Je me suis documenté un peu sur le KEYSC. (en me basant sur celui présent dans la doc du SH7724).
Pour ma part j'aimerait mettre en pause le cpu pour qu'il se réveille seulement quand l'utilisateur a appuyé sur une touche. (vu que je veux faire un shell ça me paraît logique de reposer le cpu tant qu'il ne se passe rien). Avec la doc du 7724 ce n'est pas trop compliquer à mettre en place car avec le registre KYCR1.SCN on peut lui spécifier la fréquence du scan (même si on ne peut pas spécifier précisément ce qu'on veut c'est déjà pas mal) donc ça nous évite d'utiliser un timer, et de réécrire un driver (et il génère une interruption quand une touche est pressée (logique : E)).

Seulement voilà, j'ai l'impression que le SH7305 n'a pas le même KEYSC que le SH7724 car quand j'essaie de lire les registres j'obtiens des infos complètement erronées. Pourtant le KEYSC que j'utilisais avant se trouve à l'address 0xa44b0000 et le registre KYCR1.SCN (ainsi que toute la structure du KEYSC) du 7724 se trouve au même endroit.
Me serais-je tout simplement trompé dans mon code ou, effectivement, le KEYSC n'a rien à voir avec celui du 7724 ?
Lephenixnoir En ligne Administrateur Points: 17460 Défis: 142 Message

Citer : Posté le 04/02/2019 16:38 | #


Yatis a écrit :
Je me suis documenté un peu sur le KEYSC. (en me basant sur celui présent dans la doc du SH7724).

Désolé, mais tu peux tout jeter. Il n'a rien à voir.

C'est un tableau de bits où chaque bit représente l'état d'une touche. Vois par ici : http://www.casiopeia.net/forum/viewtopic.php?p=14191#p14191

Pour ma part j'aimerait mettre en pause le cpu pour qu'il se réveille seulement quand l'utilisateur a appuyé sur une touche. (vu que je veux faire un shell ça me paraît logique de reposer le cpu tant qu'il ne se passe rien).

L'interruption de code be0 (de mémoire) se produit quand on appuie sur une touche, mais essentiellement tu ne peux pas détecter le relâchement à moins d'avoir un timer. Donc c'est un peu inutile, personnellement je la désactive.
Yatis En ligne Membre Points: 492 Défis: 0 Message

Citer : Posté le 04/02/2019 18:27 | #


Lephenixnoir a écrit :
Désolé, mais tu peux tout jeter. Il n'a rien à voir.

C'est un tableau de bits où chaque bit représente l'état d'une touche.

Effectivement c'est ce que je viens de voir :/ D'ailleurs le shadowing et bien présent avec le KEYSC du coup je comprends pourquoi on ne peut pas le corriger "avec du code"

Lephenixnoir a écrit :
L'interruption de code be0 (de mémoire) se produit quand on appuie sur une touche, mais essentiellement tu ne peux pas détecter le relâchement à moins d'avoir un timer. Donc c'est un peu inutile, personnellement je la désactive.

C'est biens le code be0 qui se produit...et comment on peut le clear ?
Au passage je vais surement déassembler le syscall 0x24a et 0x117 histoire de voir l'initialisation et le fonctionnement du KEYSC (c'est une bonne idée ou tout simplement inutile ?).
Lephenixnoir En ligne Administrateur Points: 17460 Défis: 142 Message

Citer : Posté le 04/02/2019 18:53 | #


Oups, on dit pas shadowing (ça c'est moins qui dit n'importe quoi), mais ghosting ou roll-over ! x)

Je ne sais pas comment la clear, je l'ai donc désactivée. Tu peux les désassembler, mais si tu veux j'ai déjà une version annotée et détaillée du premier, qui est le plus important.
Yatis En ligne Membre Points: 492 Défis: 0 Message

Citer : Posté le 05/02/2019 12:17 | #


Lephenixnoir a écrit :
Je ne sais pas comment la clear, je l'ai donc désactivée. Tu peux les désassembler, mais si tu veux j'ai déjà une version annotée et détaillée du premier, qui est le plus important.

Si ça ne te dérange pas j'aimerais bien voir tes notes

Lephenixnoir a écrit :
Oups, on dit pas shadowing (ça c'est moins qui dit n'importe quoi), mais ghosting ou roll-over ! x)

Ha... xD
Lephenixnoir En ligne Administrateur Points: 17460 Défis: 142 Message

Citer : Posté le 05/02/2019 22:02 | # | Fichier joint


Voilà mes notes, en pièce jointe.

Au passage, j'ai les numéros 013, 24b, 159, un court désassemblage du bootcode et une analyse poussée du TMU, côté SH4. J'uploaderai certainement ça sur la bible à l'occasion.

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
Pour coloriser votre code, cliquez ici.
Sinon cliquez sur le bouton ci-dessous.
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2020 | Il y a 58 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd