IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

Assembleur dans Arduino


Sujet :

Arduino

  1. #21
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Bonjour,

    Dans le code précédent, il y a un petit défaut.

    Si xy > 255, la composante G qui doit varier de 0 à 63 a une résolution "dégradée", la variation se fait sur 5 bits (G = (0 ... 31) * 2) au lieu de 6

    Le code suivant corrige cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    uint16_t ColGradient_Colour_Calc(int xy) {
       if (ColGradient_Swap) xy = ColGradient_WH - xy; else xy -= ColGradient_XY_min;
       if (xy < 0) return ColGradient1;
       uint16_t delta = ColGradient_XY_delta;
       if (xy > delta) return ColGradient2;
    	// ColGradient_Type 
    	//   00000000 Gradient      
    	//   01000000 Rainbow       
    	//   11000000 Rainbow Inv   
    	//   10000000 FixedMiddle
       if (ColGradient_Type == 0b10000000) return Colour[Coul_Index];
       byte R, G, B, A;
       if (ColGradient_Type & 0b01000000) {
    	  if (xy > 255) {
    		delta = ((uint32_t)xy << 8) / delta;                     
    		//A = delta << 1; 
    	  } else {
    		delta = (xy << 8) / delta;                     
    		//A = delta;
    	  }
    	  A = delta;
    	  // A =  0 -> 255   
          if (ColGradient_Type & 0b10000000) A = 255 - A; 
          if (A < 128) {
             if (A < 64) return 0xF800 | (A << 5);   // A = 0-> 63    R = 31     G = 0->63  B = 0
             R = 63 - (A >> 1);                      // A = 64->127   R = 31->0  G = 63     B = 0
             return (R << 11) | 0x7E0;                            
          }
          if (A < 192) {                             // A = 128->191  R = 0      G = 63->0  B = 0->31
             G = 191 - A;                                         
             B = (A >> 1) - 64;
             return (G << 5) | B;
          }
          R = (A >> 1) - 96;                         // A = 192->255  R = 0->31  G = 0      B = 31
          return (R << 11) | 31;                                  
        }                                             
    	R = ColGradient_R;
    	G = ColGradient_G;
    	B = ColGradient_B;
    	A = (xy << 6) / delta;
    	if (ColGradient_DR !=0) R += (ColGradient_DR * A) >> 6;
    	if (ColGradient_DG !=0) G += (ColGradient_DG * A) >> 6;
    	if (ColGradient_DB !=0) B += (ColGradient_DB * A) >> 6;
       return (R << 11) | (G << 5) | B;
    }
    Par rapport au code optimisé précédent, la perte de performance reste limitée :

    34 octets de flash en plus
    Pour la vitesse :
    - Fixed Middle H : perte moyenne de 1,0%
    - Fixed Middle V : perte moyenne de 0,6%
    - Normal H : perte moyenne de 1,0%
    - Normal V : perte moyenne de 0,6%
    - Rainbow H : perte moyenne de 1,2%
    - Rainbow V : perte moyenne de 3,7%

    Ca reste cependant plus performant que la version initiale, et cette fois-ci c'est parfaitement équivalent

    La différence n'est cependant pas perceptible... L'afficheur TFT ILI9341 a du mal à rendre les couleurs avec fidélité... on le voit assez bien lorsque le dégradé est fait sur l'écran entier.
    En revanche c'est plus joli lorsque le dégradé est fait sur un motif plus "aéré" ou plus petit.
    5 bits de résolution pour G reste suffisant
    Conclusion si on veut de la rapidité et qu'on souhaite gagner un peu de flash autant rester sur la version précédente.

    Espérons que cela soit utile à ceux qui utilisent cet afficheur.

    un dégradé sur un écran entier est un test assez difficile pour un afficheur, c'est une bonne façon de comparer les afficheurs entre eux.
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  2. #22
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Voici une version "5 bits", A ne varie que de 0 à 127, elle est un petit peu plus rapide (1%) et qui économise un peu de flash

    les parties en commentaire permettent de choisir les autres versions

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    uint16_t ColGradient_Colour_Calc(int xy) {
    	if (ColGradient_Swap) xy = ColGradient_WH - xy; else xy -= ColGradient_XY_min;
    	if (xy < 0) return ColGradient1;
    	uint16_t delta = ColGradient_XY_delta;
    	if (xy > delta) return ColGradient2;
    	// ColGradient_Type 
    	//   00000000 Gradient      
    	//   01000000 Rainbow       
    	//   11000000 Rainbow Inv   
    	//   10000000 FixedMiddle
    	if (ColGradient_Type == 0b10000000) return Colour[Coul_Index];
    	byte R, G, B, A;
    	if (ColGradient_Type & 0b01000000) {
    /*
    		// 4% Slower but accurate on G value when xy > 255
    		if (xy > 255) {
    			delta = ((uint32_t)xy << 8) / delta;                     
    		} else {
    			delta = (xy << 8) / delta;                     
    		}
    		A = delta;
    */
    /*
    		// 1% Slower but less accurate on G value when xy > 255 -  Save 17 bytes of flash
    		if (xy > 255) {
    			delta = (xy << 7) / delta;                     
    			A = delta << 1; 
    		} else {
    			delta = (xy << 8) / delta;                     
    			A = delta;
    		}
    		if (ColGradient_Type & 0b10000000) A = 255 - A; 
    		// A =  0 -> 255   
    		if (A < 128) {
    			if (A < 64) return 0xF800 | (A << 5);   // A = 0-> 63    R = 31     G = 0->63  B = 0
    			R = 63 - (A >> 1);                      // A = 64->127   R = 31->0  G = 63     B = 0
    			return (R << 11) | 0x7E0;                            
    		}
    		if (A < 192) {                             // A = 128->191  R = 0      G = 63->0  B = 0->31
    			G = 191 - A;                                         
    			B = (A >> 1) - 64;
    			return (G << 5) | B;
    		}
    		R = (A >> 1) - 96;                         // A = 192->255  R = 0->31  G = 0      B = 31
    		return (R << 11) | 31;                                  
    */
    		// Faster but less accurate on G value - Save 44 bytes of flash
    		delta = (xy << 7) / delta;                     
    		A = delta; 
    		if (ColGradient_Type & 0b10000000) A = 127 - A; 
    		// A =  0 -> 127   
    		if (A < 64) {
    			if (A < 32) return 0xF800 | (A << 6); // A = 0-> 31    R = 31     G = 0->63  B = 0
    			R = 63 - A;                      	  // A = 32->63   R = 31->0  G = 63     B = 0
    			return (R << 11) | 0x7E0;                            
    		}
    		if (A < 96) {                             // A = 64->95  R = 0      G = 63->0  B = 0->31
    			G = 191 - (A << 1);                                         
    			B = A - 64;
    			return (G << 5) | B;
    		}
    		R = A - 96;                               // A = 96->127  R = 0->31  G = 0      B = 31
    		return (R << 11) | 31;                                  
    	}                                             
    	R = ColGradient_R;
    	G = ColGradient_G;
    	B = ColGradient_B;
    	A = (xy << 6) / delta;
    	if (ColGradient_DR !=0) R += (ColGradient_DR * A) >> 6;
    	if (ColGradient_DG !=0) G += (ColGradient_DG * A) >> 6;
    	if (ColGradient_DB !=0) B += (ColGradient_DB * A) >> 6;
    	return (R << 11) | (G << 5) | B;
    }
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  3. #23
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Encore une amélioration

    7,4% de gain sur le dégradé normal H
    4,2% de gain sur le dégradé normal V
    et 70 octets de flash en moins

    en ne faisant pas grand chose : en calculant 'A' une seule fois, que ce soit pour le rainbow ou le gradient normal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    uint16_t ColGradient_Colour_Calc(int xy) {
    	if (ColGradient_Swap) xy = ColGradient_WH - xy; else xy -= ColGradient_XY_min;
    	if (xy < 0) return ColGradient1;
    	uint16_t delta = ColGradient_XY_delta;
    	if (xy > delta) return ColGradient2;
    	// ColGradient_Type 
    	//   00000000 Gradient      
    	//   01000000 Rainbow       
    	//   11000000 Rainbow Inv   
    	//   10000000 FixedMiddle
    	if (ColGradient_Type == 0b10000000) return Colour[Coul_Index];
    	byte R, G, B, A;
    	A = (xy << 7) / delta; // A =  0 -> 127   
    	if (ColGradient_Type & 0b01000000) {
    		if (ColGradient_Type & 0b10000000) A = 127 - A; 
    		if (A < 64) {
    			if (A < 32) return 0xF800 | (A << 6); // A = 0-> 31   R = 31     G = 0->63  B = 0
    			R = 63 - A;                      	  // A = 32->63   R = 31->0  G = 63     B = 0
    			return (R << 11) | 0x7E0;                            
    		}
    		if (A < 96) {                             // A = 64->95   R = 0      G = 63->0  B = 0->31
    			G = 95 - A;                                         
    			B = A - 64;
    			return (G << 6) | B;
    		}
    		R = A - 96;                               // A = 96->127  R = 0->31  G = 0      B = 31
    		return (R << 11) | 31;                                  
    	}                                             
    	R = ColGradient_R;
    	G = ColGradient_G;
    	B = ColGradient_B;
    	if (ColGradient_DR !=0) R += (ColGradient_DR * A) >> 7;
    	if (ColGradient_DG !=0) G += (ColGradient_DG * A) >> 7;
    	if (ColGradient_DB !=0) B += (ColGradient_DB * A) >> 7;
    	return (R << 11) | (G << 5) | B;
    }
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  4. #24
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 324
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 324
    Points : 4 134
    Points
    4 134
    Par défaut Gains du loto municipal
    Bonjour,

    Comme je le craignais, c'est beaucoup de travail pour des gains glorieux mais finalement assez modestes .

    J'avais écrit une variante sans les variables RGB (tout dans les return). On gagne un peu de place mais bien sûr pas de vitesse.

    Je crois que nous ne sommes pas loin de la limite de l'approche point par point. C'est intéressant intellectuellement mais ça ne répond pas vraiment à ton besoin.

    Bonne continuation.
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  5. #25
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Citation Envoyé par Guesset Voir le message
    Comme je le craignais, c'est beaucoup de travail pour des gains glorieux mais finalement assez modestes .
    Les chiffres que j'ai donné sont des moyennes ; avec le dégradé et le rainbow, j'ai gagné plus de 25% de temps d'execution sur les fonctions graphiques les plus lentes, c'est pas mal !

    Et en plus, j'ai gagné 270 octets de flash, de quoi perfectionner une autre fonction. Et s'il n'y a plus rien à améliorer, je peux ajouter des caractères aux polices de caractères en flash c'est bien aussi :-)

    Après c'est sûr, j'arrive à la fin du projet, il n'y a plus grand chose à gratter.

    A bientôt
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  6. #26
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 324
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 324
    Points : 4 134
    Points
    4 134
    Par défaut Esprit d'escalier
    Bonjour,

    Le dépassement des 255 par XY me fait penser à quelque chose : est-ce que Delta est systématiquement la largeur ou la longueur (240 ou 320) ? Si c'est le cas, il y a encore du potentiel d'optimisation.

    C'était pour te motiver pour le weekend

    Salut
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  7. #27
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Citation Envoyé par Guesset Voir le message
    Le dépassement des 255 par XY me fait penser à quelque chose : est-ce que Delta est systématiquement la largeur ou la longueur (240 ou 320) ?
    XY et Delta peuvent prendre n'importe quel valeur entre 0 et la taille de l'écran (ici, 240 ou 320)

    Delta est "la longueur" du dégradé ; XY la position de la couleur à dessiner.

    D'ailleurs, si on accepte que l'utilisateur puisse choisir un Delta de '0' (utile pour juste avoir deux couleurs) il faut remplacer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (xy > delta) return ColGradient2;
    par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ((xy > delta)||(delta == 0)) return ColGradient2;
    Sinon, division par zéro
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  8. #28
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 324
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 324
    Points : 4 134
    Points
    4 134
    Par défaut Tant pis
    Bonsoir,

    Citation Envoyé par electroremy Voir le message
    XY et Delta peuvent prendre n'importe quel valeur entre 0 et la taille de l'écran (ici, 240 ou 320)
    Tant pis, il est toujours possible de remplacer 1/Delta par une approximation u >> n mais s'il faut calculer u à chaque fois que Delta change, une fonction est nécessaire et j'ai cru comprendre que la place devient rare. Exemple avec Delta = 320 une solution est u = 51 et n = 14 : (xy << 7)/Delta -> (xy << 7)*(51/214) =(xy * 51) >> 7.

    Citation Envoyé par electroremy Voir le message
    D'ailleurs, si on accepte que l'utilisateur puisse choisir un Delta de '0' (utile pour juste avoir deux couleurs) il faut remplacer if (xy > delta) return ColGradient2; par if ((xy > delta)||(delta == 0)) return ColGradient2; Sinon, division par zéro
    Oui. J'avais déjà fait cet ajout (par sécurité avec delta <= 0) mais pas au bon endroit puisque j'affectais la ColGradient1.

    Salut.
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

Discussions similaires

  1. introduire du code assembleur dans un programme C++
    Par hzaki1986 dans le forum C++
    Réponses: 1
    Dernier message: 14/04/2007, 17h14
  2. Problème d'inclusion de code Assembleur dans du C
    Par tnarol dans le forum x86 32-bits / 64-bits
    Réponses: 5
    Dernier message: 06/09/2006, 18h56
  3. probleme d'insertion de code assembleur dans du c++
    Par Pragmateek dans le forum C++
    Réponses: 4
    Dernier message: 05/03/2006, 23h30
  4. Réponses: 5
    Dernier message: 14/01/2006, 15h16
  5. EDI pour intégrer efficacement de l'assembleur dans du C/C++
    Par Selenite dans le forum Choisir un environnement de développement
    Réponses: 2
    Dernier message: 04/04/2004, 18h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo