hello je rencontre un problème:
la fonction bitRead() travaille sur un unsigned long long (64 bits)
la fonction bitWrite() travaille sur ...32 bits.
j'ai besoin de travailler sur 64 bits dans les deux fonctions.
c'est le même problème qu'avec la fonction map(). pour laquelle on en refait une " maplong()"
peut être puis je pomper la fonction dans le source Arduino et l'adapter à mon besoin.
oui mais voilà : ou trouver le source de la fonction bitWrite() ?
J'ajoute : merci pour la question, cela m'a permis de découvrir qu'avec la version 2.3.2 de l'IDE, que j'avais téléchargée, mais pas ouvert, Arduino SA a modifié la structure de l'installation.
Le répertoire visible ne contient plus que le lanceur.
Toutes les bibliothèques et le code des fonctions arduino se retrouve dans le répertoire .arduino15 (non visible sous Linux sauf à cliquer sur "afficher les fichiers cachés").
Arduino SA s'est aligné sur l'organisation PlatformIO où les différents frameworks sont dans le répertoire (non visible sous Linux) .platformio
Autre point : je pense avoir compris que le framework avr n'a pas été mis à jour depuis la 1.8.6
Ouais, mais mon message était rédigé et je profitais du temps que je croyais avoir pour flâner dans le fichier Arduino.h.
Et paf, tu profites de ma promenade arduinolesque pour dire que tu as trouvé, c'est po juste.
pour le read, c'est juste un décalage de N bits, le compilateur va se débrouiller
Mais pour le write, ils fabriquent un masque en décalant la valeur 1 de N positions mais ce 1 est stocké dans un uint32_t et pas un uint64_t car ils utilisent 1UL et pas 1ULL
donc si vous décalez de 33 positions ce 1 qui est représenté sur 32 bits, ben le 1 "tombe au bout" des 32 bits et ça fait 0...
si vous redéfinissez ces fonctions en changeant un peu leur nom (toutes n'auraient pas l'être mais autant être homogène)
bonjour , pour la culture :
souvent pour les décalages à gauche , le compilateur préfère multiplier par une puissance de 2 , ça prend moins de cycles
un ARM , par exemple , ne fera pas cela , car il peut décaler de plusieurs cases en 1 seule instruction
Non, un compilateur ne préfère pas utiliser une multiplication par une puissance de 2 pour faire un décalage à gauche.
Au contraire, il utilisera l’instruction de décalage binaire directe. Les processeurs modernes ainsi que les plus anciens ont des instructions spécifiques pour les décalages qui sont plus rapides qu’une multiplication.
Le décalage à gauche est une opération beaucoup plus simple à réaliser en termes de cycles machine, et les compilateurs optimisent généralement en utilisant l’instruction de décalage plutôt qu’une multiplication, car c’est plus efficace.
Je pense que vous confondez avec l’inverse. Quand le compilateur voit une multiplication d’un entier par une puissance de deux, il la remplace par un décalage,
PS que crois qu’il faut remonter à l’architecture PDP-8 (un mini-ordinateur des années 1960) pour trouver un processeur très simple qui n’avait pas d’instructions spécifiques pour le décalage binaire
c'est ce que j'avais vu en regardant le fichier assembleur ... et je ne suis pas à ce point atteint de gâtisme : pour un AVR , la multiplication est + performante quand il s'agit de décaler à gauche de plusieurs cases à la fois
Sur 8 bits et plusieurs bits de décalage oui, un mul c’est 2 cycles et un shift 1 cycle. Donc à plus de 2 bits et un décalage avec une constante puissance de deux, je suis d’accord Mais sur 64 bits comme on en discute ici ce n’est pas forcément évident….
j'ai regardé et vous avez raison , il fait soit une boucle avec des additions avec la valeur elle même pour faire x2 puis x4 etc , soit un multiplication si la valeur de décalage est faible.
c'était à mon adresse pour me rassurer ; je me souviens dans quel contexte j'avais vu ça , c'était à propos d'un IC TLC5947 , driver de 24 leds , chacune dimmable sur 12 bits , ce qui en fait un registre à décalage de 288 bits , et j'en avais 3 chaînés de la sorte
j'avais d'abord utilisé la bibliothèque d'un fabricant , mais je l'avais trouvée peu satisfaisante : ils avaient placé les 12 bits de chaque led dans un uint16_t , ce qui fait perdre à chaque fois 1/2 octet de la précieuse RAM , et de plus obligeait à refaire des calculs au moment du transfert vers les ICs
alors j'ai résolu en groupant les leds par paires , et en plaçant les 24 bits ainsi obtenus dans 3 octets , donc économie de RAM , et au moment du transfert , il suffit (j'utilise le SPI) d'envoyer les octets comme ils viennent
mais pour ceci , au moment de placer dans la RAM , il faut prélever un tiers de chacun des 2 mots de 12 bits , et les placer dans l'octet du milieu , et il fallait notamment prendre un nibble de poids faible , pour le placer sur le poids fort , en décalant de 4 cases vers la gauche ; c'est là que j'ai vu que le compilateur multiplie par 16 (2cycles) , au lieu de décaler 4 fois (4cycles) , alors que j'avais utilisé l'opérateur <<
pour 64 bits , pareil , je ne sais pas
en regardant un peu l'assembleur, j'ai vu que le compilateur choisit de faire soit des additions, soit des multiplications suivant la taille de ce sur quoi on travaille et du décalage voulu
Bien que résolu, il est intéressant d'étudier la méthode d'implémentation d'une multiplication 8 bits x 8 bits en 2 cycles du µC (cf. § 31. Instruction Set Summary - Page 281/294 de la datasheet) qui, sauf erreur de ma part, ne peut pas être faite d'une manière "micro" codée avec un quelconque algorithme séquentiel...
Je pense plutôt à une implémentation sous la forme d'un accès à une mémoire interne préprogrammée qui fournit les 65536 résultats en une seule opération sans l'exécution d'un algorithme