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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    994
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 994
    Par défaut Assembleur dans Arduino
    Bonjour,

    J'ai quasi terminé mon projet d'interface ethernet avec écran TFT tactile.
    Le matériel utilisé est Arduino UNO + ILI9341 TFT + XPT2046 touch + Shield Ethernet II

    Une fonction impacte fortement la vitesse d'affichage
    Elle sert à faire des "dégradés" de couleur :
    - les dégradés peuvent être hozirontaux ou verticaux (couleur fonction de X ou de Y)
    - le dégradé peut être "normal" (couleur de départ -> couleur d'arrivée)
    - le dégradé peut être "arc en ciel"
    - il y a un dégradé "fixed middle", c'est un mode "3 couleurs" : couleur de départ si X < début, couleur d'arrivée si X > fin et couleur fixe à la place du dégradé

    Cela peut sembler étrange mais c'est très pratique.
    Par exemple vous voulez dessiner un graphique type "équaliseur HiFi", hé bien grâce au dégradé "fixed middle" vous dessinez les rectangles de votre équaliseur et ils auront automatiquement la zone verte, la zone jaune éventuelle et la zone rouge éventuelle comme il faut.

    Les dégradés permettent des effets visuels intéressants qui compensent le fait qu'on ne puisse faire que des graphismes monochromes (à la base, une forme élémentaire n'a qu'une seule couleur) et sans antialiasing
    Ainsi, en mettant un rectangle, un ou deux triangles ou un bitmap dessinés avec une couleur dégradée, on peut avoir des dessins ou des icônes donnant une impression de relief ou une impression de couleur comme sur un écran d'ordinateur.
    Cela permet à ma petite interface qui a peu de ressources de proposer des graphismes dignes de l'an 2020

    J'ai en grande partie résolu le problème de performance en appelant cette fonction le moins souvent possible.
    En fonction du type de dégradé (horizontal ou vertical), je me débrouille pour dessiner les graphismes soit avec des segments de droite horizontaux ou soit avec des segments de droite verticaux.
    Du coup la fonction est appelée un fois par ligne au lieu d'être appelée "bêtement" à chaque pixel.
    C'est très efficace.
    Je peux faire un dégradé qui remplit tout l'écran et ça ne demande que 7% de temps d'execution en plus qu'avec une couleur unique (186 millisecondes au lieu de 174)

    Mais j'ai quand même quelques fonctions graphiques où ce principe ne peut pas être utilisé, et donc il faut calculer la couleur pour chaque pixel
    J'ai aussi des fonctions graphiques qui ne dessinent que de petits segments de droite horizontaux ou verticaux, elles sont pénalisées.
    Dans le cas le plus défavorable, typiquement une page de texte "opaque" avec couleur dégradé pour le texte et pour le fond, on peut dépasser une seconde pour l'affichage.

    Rien de dramatique, si vous connaissez la librairie ILI9341 Adafruit vous trouverez certainement que ma version est déjà bien plus rapide !

    J'ai fait un benchmark et la plupart des exemples sont rapides (moins de 200 ms) et la quasi totalité est sous les 400 ms.
    J'aimerais bien arriver à optimiser encore un petit peu plus pour que tout soit rapide

    Voici la fonction :

    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
    74
    75
    76
     
    // Variables globales
    uint8_t ColGradient_R; // R value when X or Y = ColGradient_XY_min
    uint8_t ColGradient_G;
    uint8_t ColGradient_B;
    int8_t ColGradient_DR; // R value when X or Y = ColGradient_XY_min + ColGradient_XY_delta is ColGradient_R + ColGradient_DR 
    int8_t ColGradient_DG;
    int8_t ColGradient_DB;
    bool ColGradient_Mode;
    bool ColGradient_X_Direction;
    int ColGradient_XY_min;
    int ColGradient_XY_delta;
    bool ColGradient_Swap;
    int ColGradient_WH;
     
    // ...
     
    unsigned int ColGradient_Colour_Calc(int xy) {
    	if (ColGradient_Swap) {
    		xy = ColGradient_WH  - xy;
    	} else {
    		xy -= ColGradient_XY_min;
    	}
    	int delta = ColGradient_XY_delta;
    	if (xy >= delta) {
    		return ColGradient2;
    	} else if (xy <= 0) {
    		return ColGradient1;
    	} else {
    		// ColGradient_Type 
    		// 00000000 Gradient      
    		// 01000000 Rainbow       
    		// 11000000 Rainbow Inv   
    		// 10000000 FixedMiddle   
    		if (ColGradient_Type == 0b10000000) {
    			return Colour[Coul_Index];
    		} else {
    			byte R;
    			byte G;
    			byte B;
    			if (ColGradient_Type & 0b01000000) {
    				if (ColGradient_Type & 0b10000000) xy = delta - xy;
    				xy *= 4;
    				if (xy < delta) {
    					R = 31;
    					G = 63 * xy / delta;
    					B = 0;
    				} else if (xy < 2 * delta) {
    					R = 31 * (2 * delta - xy) / delta;
    					G = 63;
    					B = 0;
    				} else if (xy < 3 * delta) {
    					R = 0;
    					G = 63 * (3 * delta - xy) / delta;
    					B = 31 * (xy - 2 * delta) / delta;
    				} else {
    					R = 31 * (xy - 3 * delta) / delta;
    					G = 0;
    					B = 31;
    				}
    			} else {
    				R = ColGradient_R;
    				G = ColGradient_G;
    				B = ColGradient_B;
    				//if (ColGradient_DR !=0) R += ColGradient_DR * xy / delta;
    				//if (ColGradient_DG !=0) G += ColGradient_DG * xy / delta;
    				//if (ColGradient_DB !=0) B += ColGradient_DB * xy / delta;
    				byte k = (xy << 6) / delta;
    				if (ColGradient_DR !=0) R += (ColGradient_DR * k) >> 6;
    				if (ColGradient_DG !=0) G += (ColGradient_DG * k) >> 6;
    				if (ColGradient_DB !=0) B += (ColGradient_DB * k) >> 6;
    			}
    			return (R << 11) | (G << 5) | B;
    		}
    	}
    }
    Je me demande si je ne devrais pas coder cette fonction en assembleur.
    Ou au moins la partie la plus lente qui est celle-ci :

    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
     
    			byte R;
    			byte G;
    			byte B;
    			if (ColGradient_Type & 0b01000000) {
    				if (ColGradient_Type & 0b10000000) xy = delta - xy;
    				xy *= 4;
    				if (xy < delta) {
    					R = 31;
    					G = 63 * xy / delta;
    					B = 0;
    				} else if (xy < 2 * delta) {
    					R = 31 * (2 * delta - xy) / delta;
    					G = 63;
    					B = 0;
    				} else if (xy < 3 * delta) {
    					R = 0;
    					G = 63 * (3 * delta - xy) / delta;
    					B = 31 * (xy - 2 * delta) / delta;
    				} else {
    					R = 31 * (xy - 3 * delta) / delta;
    					G = 0;
    					B = 31;
    				}
    			} else {
    				R = ColGradient_R;
    				G = ColGradient_G;
    				B = ColGradient_B;
    				//if (ColGradient_DR !=0) R += ColGradient_DR * xy / delta;
    				//if (ColGradient_DG !=0) G += ColGradient_DG * xy / delta;
    				//if (ColGradient_DB !=0) B += ColGradient_DB * xy / delta;
    				byte k = (xy << 6) / delta;
    				if (ColGradient_DR !=0) R += (ColGradient_DR * k) >> 6;
    				if (ColGradient_DG !=0) G += (ColGradient_DG * k) >> 6;
    				if (ColGradient_DB !=0) B += (ColGradient_DB * k) >> 6;
    			}
    			return (R << 11) | (G << 5) | B;
    Dans mon projet j'ai déjà des bouts d'assembleur provenant des bibliothèques que j'ai modifié ; voici un example :

    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
     
    	// 17 cycle delay (including "call")
    	static void delay17() __attribute__((noinline)) __attribute__((naked))	{
    		__asm__ __volatile__
    		(
    									// +4 (call to get here)
    			"	adiw	r24,0\n"	// +2 (2-cycle NOP)
    			"	adiw	r24,0\n"	// +2 (2-cycle NOP)
    			"	adiw	r24,0\n"	// +2 (2-cycle NOP)
    			"	adiw	r24,0\n"	// +2 (2-cycle NOP)
    #if !defined(__AVR_HAVE_RAMPD__)	
    			"	nop\n"				// +1 (2-cycle NOP)
    #endif
    			"	ret\n"				// +4 (or +5 on >64KB AVR with RAMPD reg)
    									// = 17 cycles
    			: : : 
    		);
    	}
     
    	// SPI 16-bit write with minimal hand-tuned delay (assuming max DIV2 SPI rate)
    	static INLINE void spiWrite16(uint16_t data) INLINE_OPT	{
    		uint8_t temp;
    		__asm__ __volatile__
    		(
    			"	out	%[spi],%[hi]\n"				// write SPI data (18 cycles until next write)
    			"	call	_ZN11PDQ_ILI93417delay17Ev\n"	// call mangled delay17 (compiler would needlessly save/restore regs)
    			"	out	%[spi],%[lo]\n"				// write SPI data (18 cycles until next write)
    			"	call	_ZN11PDQ_ILI93417delay17Ev\n"	// call mangled delay17 (compiler would needlessly save/restore regs)
     
    			: [temp] "=d" (temp)
    			: [spi] "i" (_SFR_IO_ADDR(SPDR)), [lo] "r" ((uint8_t)data), [hi] "r" ((uint8_t)(data>>8))
    			: 
    		);
    	}
    Qu'en pensez vous ?

    Sans surprise, c'est les multiplications et surtout la division qui est coûteuse.
    La ligne "byte k = (xy << 6) / delta" qui permet d'économiser jusque 3 divisions m'a fait gagné pas mal de temps (c'est une astuce un peu barbare qui tiens compte du fait que les couleurs sont sur 16 bits donc R5 G6 B5)

    Comment faire, ou trouver des ressources ?

    Même si ça ne marche pas et/ou si l'optimisation est faible, ce sera toujours une chose intéressante à essayer et à faire

    A bientôt

  2. #2
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 607
    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 607
    Par défaut Couleurs, dégradés et plus si affinités
    Bonjour,

    Il est possible de multiplier facilement les performances en considérant qu'un dégradé n'est qu'une collection de droites : R(x) = dR*(x-x0) + R0, G(x) = dG*(x-x0) + G0, B(x) = dB*(x-x0) + B0 avec dR = (R1-R0)/(x1-x0) etc.

    La deuxième considération est que ce sont de ligne discrètes.

    Il s'ensuit que les algorithmes de Bresenham, du demi-point fonctionnent très bien et évitent toute multiplication et division : voir https://fr.wikipedia.org/wiki/Algori...t_de_Bresenham.

    Pour faire des choses plus variées, il est possible de travailler avec une seule droite y(x) servant d'indice dans un tableau de couleurs (par exemple rainbow) mais ça occupe de la mémoire.

    Salutations

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

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 994
    Par défaut
    Bonjour,

    J'ai eu les mêmes idées que toi

    Citation Envoyé par Guesset Voir le message
    Il est possible de multiplier facilement les performances en considérant qu'un dégradé n'est qu'une collection de droites : R(x) = dR*(x-x0) + R0, G(x) = dG*(x-x0) + G0, B(x) = dB*(x-x0) + B0 avec dR = (R1-R0)/(x1-x0)
    Dans ton exemple, DR est un float et en termes de performance c'est pire, sans parler de la taille du code.

    Mon calcul n'utilise que des entiers, les divisions sont des divisions entières.

    Citation Envoyé par Guesset Voir le message
    Il s'ensuit que les algorithmes de Bresenham, du demi-point fonctionnent très bien et évitent toute multiplication et division : voir https://fr.wikipedia.org/wiki/Algori...t_de_Bresenham.
    Je connais cet algorithme, je m'en sert pour les droites et les cercles.

    Le soucis est que je n'appelle pas forcément le calcul du dégradé "dans l'ordre", c'est à dire avec des valeurs croissantes et contigües de X ou Y
    Or Bresenham est un algorithme itératif... donc ce n'est pas possible.

    Citation Envoyé par Guesset Voir le message
    Pour faire des choses plus variées, il est possible de travailler avec une seule droite y(x) servant d'indice dans un tableau de couleurs (par exemple rainbow) mais ça occupe de la mémoire.
    En effet, ça occupe de la mémoire : 16 bits (2 octets) par couleur x 320 pixels = 640 octets pour un dégradé, il faudrait 640 autres pour le dégradé du fond, soit 1280 octets, les 2/3 de la RAM de l'Arduino UNO, ce n'est pas possible pour mon application

    Mon idée est de passer tout ou partie de cette fonction en assembleur, si j'arrive à gagner quelques cycles ce serait pas mal.

    A bientôt

  4. #4
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 607
    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 607
    Par défaut Point à point
    Bonjour,

    Citation Envoyé par electroremy Voir le message
    Dans ton exemple, DR est un float et en termes de performance c'est pire, sans parler de la taille du code.
    Ce n'est pas un exemple mais juste une présentation du problème pour amener, avec l'autre considération sur la discrétisation, les algorithmes incrémentaux. Que tu ne peux, semble-t-il, utiliser.

    Citation Envoyé par electroremy Voir le message
    En effet, ça occupe de la mémoire : 16 bits (2 octets) par couleur x 320 pixels = 640 octets pour un dégradé, il faudrait 640 autres pour le dégradé du fond, soit 1280 octets, les 2/3 de la RAM de l'Arduino UNO, ce n'est pas possible pour mon application.
    Le dégradé n'a pas nécessairement besoin de faire la largeur de l'écran. Par exemple il peut être cyclique. Et ne pas être en RAM.

    Citation Envoyé par electroremy Voir le message
    Mon idée est de passer tout ou partie de cette fonction en assembleur, si j'arrive à gagner quelques cycles ce serait pas mal.
    A chaque fois que l'assembleur permet pas de faire autrement, il y a de bonnes chances d'avoir une nette amélioration, mais si tu es contraint de reproduire le même schéma, il sera difficile de faire mieux que le compilateur.

    Une solution intermédiaire peut être. Pourquoi ne pas créer une ligne (colonne) de dégradé jetable (tableau dynamique). Tu consommerais certes de la mémoire mais seulement temporairement.

    Il y a une autre approche. Même si tu ne peux intégralement repeindre dans un dégradé, il est vraisemblable que tu ne dessines pas des points épars mais des petits segments. Auquel cas tu peux recalculer les extrémités (avec tes fonctions) mais appliquer un Bresenham au tracé proprement dit du segment. Si la taille moyenne d'un segment est, par exemple, 8 tu devrais être au moins 2 fois plus rapide (2 points classique + 6 points en Bresenham). Si le Segment est orthogonal au dégradé le gain sera plus important encore. C'est même adaptable, avec quelques efforts, à un segment en biais.

    Salut

  5. #5
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 607
    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 607
    Par défaut Nettoyage de printemps
    Bonjour,

    J'ai essayé de passer un coup de polish sur le code.

    J'ai un problème sur le rainbow. Tantôt les changements de couleur sont pointus tantôt ils présentent des méplats (et certaines valeurs non atteignables). J'ai pris l'option de systématiquement avoir des méplats ce qui permet d'avoir plus de puissances de 2 et donc moins de multiplications.
    Code C++ : 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
    unsigned int ColGradient_Colour_Calc(int xy) {
       if (ColGradient_Swap) xy = ColGradient_WH  - xy; else xy -= ColGradient_XY_min;
       int delta = ColGradient_XY_delta;
       if (xy >= delta) return ColGradient2;
       if (xy <= 0) || (delta <= 0) return ColGradient1;
       // ColGradient_Type 
       // 00000000 Gradient      
       // 01000000 Rainbow       
       // 11000000 Rainbow Inv   
       // 10000000 FixedMiddle   
       if (ColGradient_Type == 0b10000000) return Colour[Coul_Index];
       byte R;
       byte G;
       byte B;
       if (ColGradient_Type & 0b01000000) {
          if (ColGradient_Type & 0b10000000) xy = delta - xy;
          xy *= 4;
          if (xy < delta) {
             //G = (63 * xy) / delta;                  // Pas 64 ? Gmax < 63*Delta/Delta = 63, Gmax = 62
             G = (xy << 6) / delta;                  // Avec 64 Gmin = 0 -> Gmax = 63
             return 0xF800 | (G << 5);               // R = 31 et B = 0
          } else if (xy < 2 * delta) {
             R = 63 - (xy << 5) / delta;             // Eviter * 31, Rmax = 31 -> Rmin =  0
             return (R << 11) | 0x7E0;               // G = 63 et B = 0
          } else if (xy - delta < 2 * delta) {       // Eviter * 3
             G = 191 - (xy << 6) / delta;            // Eviter * 63, Gmax = 63 -> Gmin =  0
             B = (xy << 5) / delta - 64;             // Eviter * 31, Bmin =  0 -> Bmax = 31
             return (G << 5) | B;                    // R = 0
          } else {
             R = (xy << 5) / delta - 96;             // Eviter * 31, Rmin =  0 -> Rmax = 30 ?
             return (R << 11) | 31;                  // G = 0, B = 31
          }
       }                                             // Hypothèses Comp/Branch : 2, * : 6, >> : 3
       byte k = (xy << 6) / delta;                   //  test 63*(2+6+3) + 1*2 = 695, <op> = 10.85
       R = ColGradient_R + (ColGradient_DR * k) >> 6;// !test 64*(6+3) = 576,         <op> = 9
       G = ColGradient_G + (ColGradient_DG * k) >> 6;
       B = ColGradient_B + (ColGradient_DB * k) >> 6;
       return (R << 11) | (G << 5) | B;
    }
    Salut

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

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 994
    Par défaut
    Citation Envoyé par Guesset Voir le message
    Bonjour,

    J'ai essayé de passer un coup de polish sur le code.

    J'ai un problème sur le rainbow. Tantôt les changements de couleur sont pointus tantôt ils présentent des méplats (et certaines valeurs non atteignables). J'ai pris l'option de systématiquement avoir des méplats ce qui permet d'avoir plus de puissances de 2 et donc moins de multiplications.

    Salut
    Tes idées sont bonnes

    Une petite erreur if (xy <= 0) || (delta <= 0) return ColGradient1; au lieu de if ((xy <= 0) || (delta <= 0)) return ColGradient1; mais je vais pas jeter la pierre je fais ça tout le temps aussi

    Ton code est plus compact, 18 octets de flash en mois

    Il y a un bug sur le rainbow malheureusement, des bandes de couleurs ne sont pas correctes

    J'ai refait le benchmark complet, ton code est un peu plus lent que le miens (entre 1 et 10 ms de perdue pour chaque exemple)

    Il y a les optimisations du compilateur Arduino qui entrent en scène...

    Je crois me souvenir qu'on peu obtenir le code assembleur généré, il faudrait que je puisse retrouver celui correspond à la fonction, on verra vraiment si c'est optimisable ou pas.

    A bientôt

  7. #7
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 282
    Par défaut
    Bonsoir à tous

    Oui l'assembleur est spécifique, et il a même le droit à sa documentation spécifique : AVR Instruction Set Manual
    A la fin de la doc de chaque microcontrôleur il y a un tableau récapitulatif (Instruction Set Summary) reprenant les instructions supportées par ce micro en particulier. (Imprimé, il ne fait que 2 ou 3 pages, cela fait un très bon aide-mémoire). Et attention certains micros n'implémentent pas toutes les instructions.

    Locoduino vient de sortie une bonne série d'articles sur la programmation en assembleur des Arduino AVR, il reprend tout ce que je t'aurais indiqué.

    Par contre je m'insurge sur la raison de départ.
    Ce n'est pas le passage à l'ASM qui permet l'optimisation d'un programme, mais l’abandon de la couche Arduino et un algorithme adapté qui font la majorité de l'optimisation.
    Il est possible d’obtenir 99% de l'optimisation simplement en codant en C "AVR" au lieu du C++ "Arduino". Par contre connaitre l'assembleur du micro en question permet de mieux connaître le micro et d'identifier les instructions longues à exécuter et/ou grosses en mémoire.
    Dans le C "AVR" j'inclue le fait de coder en bas niveau, soit une programmation très simple n'utilisant que les opérations hardwired et optimisant les types de variable (toujours des entiers et ayant le nombre de byte minimal).

    Le seul avantage de l'ASM c'est de forcer à réfléchir sur les optimisations de l’algorithme, alors qu'en C il faut trouver où cela pèche.
    Par contre l'ASM, c'est une horreurs dans la gestion des variables (normal il n'y en a pas) et donc dès que l'on dépasse un petit programme on aura vite fait une erreur...

    Dans ton code c'est les divisions (même entières) qui doivent consommer la plus grande partie du temps de calcul, car la division n'est pas câblée, c'est une réalisation sur base de boucles.
    Calculer l'inverse de Delta (voir même avec une lookup table si c'est un byte), puis faire le calcul en prenant soit une multiplication par Delta, soit une multiplication par l'inverse de Delta (et un décalage) peut considérablement accélérer le code.

    Donc faire un apprentissage de l'assembleur, pour mieux connaître la bête, oui pourquoi pas. Faire un projet utilisant la majorité des capacités d'un Mega, c'est prise de tête assurée.

    Bonne suite

    Delias

  8. #8
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    Dans mes (vieux) cours d'assembleur, on me disait que le langage était spécifique au contrôleur programmé. En d'autres termes, il y avait assembleur et assembleur.
    Là, les instructions utilisées ne me parlent pas du tout. Tu as récupéré de l'assembleur écrit dans des bibliothèques, es-tu sûr qu'il fonctionnera avec l'Arduino que tu vas utiliser ? D'ailleurs, y a-t-il une doc Arduino sur les instructions assembleurs qu'il est possible d'utiliser ?

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

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 994
    Par défaut
    Bonjour,

    je confirme que ça fonctionne

    le code ASM est issu de la bibliothèque, et c'est le code ASM spécifique AVR / Arduino UNO de la bibliothèque d'origine

    après, c'est du code ASM pour le compilateur AVR utilisé par l'IDE Arduino (donc le compilateur de base Atmel) il y a très certainement une syntaxe particulière

    A bientôt

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