Bitwise sur une valeurd'un tableau de uint16_t

Bonjour,

J'ai un tableau de 25 uint16_t

Le but c'est de modifier certains bit d'un élément du tableau.
Dans un premier temps je fais un test avec tab[5].

en global j'ai
uint16_t buf_attr[25] = {0};

Le bits a modifié sont:

Bit 0-2
Bit 3
Bit 4-6
Bit 7
Bit 8
Bit 9
Bit 10
Bit 11
Bit 12-15

J'ai une fonction saveContext qui fait un update des bits, suivants les paramètres de cette fonction:
void saveContext(uint8_t *typeSet, uint8_t *doubleWidth, uint8_t *masque,uint8_t *doubleHeight,uint8_t *insert,uint8_t *inverse,uint8_t *fg_color, uint8_t *blink,uint8_t *bg_color)

dans le setup, le programme:

....
uint8_t typeset = 3;
  uint8_t dw = 1;
  uint8_t conceal = 1;
  uint8_t dh = 1;
  uint8_t insert = 1;
  uint8_t inverse = 1;
  uint8_t foreground = 2;
  uint8_t flash = 1;
  uint8_t background = 7;

  saveContext(&typeset, &dw, &conceal, &dh, &insert, &inverse, &foreground, &flash, &background);
  foreground = 4;
  saveContext(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &foreground, nullptr, &background);

  Serial.printf("\r\n\r\ntypeset = %d\r\n", readContext(TYPEANDSET));
  Serial.printf("double width = %d\r\n", readContext(DOUBLEWIDTH));
  Serial.printf("Conceal = %d\r\n", readContext(MASQUE));
  Serial.printf("double height = %d\r\n", readContext(DOUBLEHEIGHT));
  Serial.printf("insert = %d\r\n", readContext(INSERT));
  Serial.printf("inverse = %d\r\n", readContext(INVERSE));
  Serial.printf("foreground = %d\r\n", readContext(FOREGROUND));
  Serial.printf("flash = %d\r\n", readContext(FLASH));
  Serial.printf("background = %d\r\n", readContext(BACKGROUND));
  Serial.printf("buf_attr[5] = %04X\r\n", buf_attr[5]);
....

le probleme c'est que la valeur de l'uint16_t du tableaux est mise toujours a zero,
malgré que je fais un tests de non nullité du pointeur.

Code de saveContext:

void saveContext(uint8_t *typeSet, uint8_t *doubleWidth, uint8_t *masque,uint8_t *doubleHeight,uint8_t *insert,uint8_t *inverse,uint8_t *fg_color, uint8_t *blink,uint8_t *bg_color)
{      

  if(bg_color != nullptr) {
    buf_attr[5] = *bg_color & 7;
  }    // backgroune color
  if (blink != nullptr) {
     if (*blink & 1) bitSet(buf_attr[5], 3); else bitClear(buf_attr[5], 3); 
  }   // blink                                                          
  if (fg_color != nullptr) 
  {
    buf_attr[5] |=  (*fg_color & 7) << 4 ;
  }                                     //Foregrounf color
  if(inverse != nullptr) { 
    if (*inverse & 1) bitSet(buf_attr[5], 7); else bitClear(buf_attr[5], 7); 
  }        // inverse
  if(insert != nullptr) { 
    if (*insert & 1) bitSet(buf_attr[5], 8); else bitClear(buf_attr[5], 8); 
  }          // insert
  if(doubleHeight != nullptr) { 
    if (*doubleHeight & 1) bitSet(buf_attr[5], 9); else bitClear(buf_attr[5], 9); 
  }   // double height
  if(masque != nullptr) { 
    if( *masque & 1) bitSet(buf_attr[5], 10); else bitClear(buf_attr[5], 10); 
  }       // masquage (Conceal)
  if(doubleWidth != nullptr) { 
    if (*doubleWidth & 1) bitSet(buf_attr[5], 11); else bitClear(buf_attr[5], 11); 
  }  // double width
  if (typeSet != nullptr) {
    buf_attr[5] |= (*typeSet & 7) << 12;
  }                                         // type set
  

  Serial.printf("\r\n\r\nTypeset: %d\r\n", (buf_attr[5] >> 12) & 0xF);                   // type set
  Serial.printf("Double width: %d\r\n", bitRead(buf_attr[5], 11));               // double width
  Serial.printf("Conceal: %d\r\n", bitRead(buf_attr[5], 10));                    // madquage
  Serial.printf("Double height: %d\r\n", bitRead(buf_attr[5], 9));               // double height
  Serial.printf("Insert: %d\r\n", bitRead(buf_attr[5], 8));                      // insert
  Serial.printf("Inverse: %d\r\n", bitRead(buf_attr[5], 7));                     // inverse
  Serial.printf("Foreground: %d\r\n", (buf_attr[5] >> 4) & 7);                   // Foreground
  Serial.printf("Insert: %d\r\n", bitRead(buf_attr[5], 3));                      // blink
  Serial.printf("Background: %d\r\n\r\n", buf_attr[5] & 0x07);                   // Background

  Serial.print(buf_attr[5], HEX);
  Serial.printf("\r\nbuf_attr[5] = 0x%04X\r\n", buf_attr[5]);
}

La variale global est bien modifié au premier passage de saveContext, mais au deuxième, la ou il y a nullptr, elle sont à 0, malgré un test du if (valeur != nullptr).

sortie du programme:

Typeset: 3
Double width: 1
Conceal: 1
Double height: 1
Insert: 1
Inverse: 1
Foreground: 2
Insert: 1
Background: 7

3FAF
buf_attr[5] = 0x3FAF


Typeset: 0
Double width: 0
Conceal: 0
Double height: 0
Insert: 0
Inverse: 0
Foreground: 4
Insert: 0
Background: 7

47
buf_attr[5] = 0x0047


typeset = 0
double width = 0
Conceal = 0
double height = 0
insert = 0
inverse = 0
foreground = 4
flash = 0
background = 7
buf_attr[5] = 0047

Au deuxième passage on voit que typeset aurait du avoir la valeur 3 ui a été modifié auparavant, car je dis en gros,
ne touche pas a cette valeur si ce paramètre est null ou bien je fais l'action si c'est différent de nullptr.

J'utilise directement la valeur buf_attr[5], mais j'ai aussi essayé de passer par une valeur intermédiaire, ca ne change rien.

La valeur global garde sa valeur si on y touche pas ?
J'ai essayé de la mettre static mais ca ne change rien.

Quand je parle de variable globale je parle du tableau qui est global, si on change son contenu il reste en mémoire, il ne se remet pas à 0.
Merci de votre aide.

vous devriez utiliser une structure avec des champs de bits.

attention je suppose que vous vous êtes trompé pour background ça doit être au max 4 bits sinon vous ne tenez pas dans un uint16_t

struct __attribute__((packed)) FieldBits {
    uint16_t typeset : 3;      // Bits 0-2
    uint16_t dw : 1;           // Bit 3
    uint16_t conceal : 1;      // Bit 4
    uint16_t dh : 1;           // Bit 5
    uint16_t insert : 1;       // Bit 6
    uint16_t inverse : 1;      // Bit 7
    uint16_t foreground : 2;   // Bits 8-9
    uint16_t flash : 1;        // Bit 10
    uint16_t background : 4;   // Bits 12-15
} ;

Sinon quand vous touhcez aux bit avec

    buf_attr[5] = *bg_color & 7;

vous modifiez tous les bits - ce qui n'est pas le cas avec bitSet ou bitClear

Si bg_color n'est pas nul tu fais *bg_color & 7; qui met à 0 tous les bits sauf les 3 derniers.
pour modifier uniquement les 3 derniers bits il faudrait faire
buf_attr[5] = (buf_attr[5] & 7) |*bg_color & 7;
le & met les bits en question à 0 dans buf_attr[5] et le | place les 3 nouveaux bits

Ce sont les trois premiers et non les trois derniers ?
les bits 0-2 c'est bg_color.

Je viens de découvrir l'erreur du |qui mettait a zero, par contre la ou j'ai pas vu c'est comme tu as fait de mettre d'abord les 3 bits a zéro.

C'est surement pour cela que pour foreground au deuxième appel j'ai 6 au lieu de 4.
par contre pour foreground dans les bits 4-6 c'est plus difficile ca se trouve au milieu.

j'ai modifié sinon en faisant = tous les autres bits sont a zero, j'ai ajouté les parentheses et mis un ou avant le égal
buf_attr[5] |= ((buf_attr[5] & 7) | (*bg_color & 7));

pour les bits 4-6 j'ai fait ceci , j'ai bien 6 pour fg_color, mais je ne sais pas si c'est bien ca:
buf_attr[5] |= ((buf_attr[5] & ( 7 << 4)) | ((*fg_color & 7) << 4)) ;

Utilise les champs de bits comme proposé par @J-M-L ça rend cette gestion transparente.

pourquoi ne pas utiliser un champ de bit ? vous vous complexifiez la vie pour rien le compilo fait ça très bien pour vous !

pour les bits 12-15 j'ai fait ceci:
buf_attr[5] |= ((buf_attr[5] & ( 0xF << 12)) | ((*typeSet & 0xF) << 12)) ;

pour moi le mot je le commence de 15 a 0 en bit
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

pour les bit 4-6 j'ai toujours 6 au lieu de 4. (fg_color ou foreground).
buf_attr[5] |= ((buf_attr[5] & ( 7 << 4)) | ((*fg_color & 7) << 4));

j'ai du faire une erreur quelque part

ces deux formules ne fonctionne pas:

if(bg_color != nullptr) {    
    buf_attr[5] |= ((buf_attr[5] & 7) | (*bg_color & 7));
  }    
et
if (typeSet != nullptr) {
    
    buf_attr[5]  |=  ((buf_attr[5] & ( 7 << 12)) | ((*typeSet & 0xF) << 12));
  }

désolé je n'avais pas vu vos message, entre temps, je vais essayer les champs de bits,
sinon c'est 3 bit par couleurs.
voir schéma ci-dessous, j'utilise le byte A et le byte B

typeset est sur 4 bits.

Je ne peux pas le faire avec la structure de bit, car il faut que ce soit dans un tableaux de 25 impérativement qui qui correspond a la line de l'écran, de 0 a 24.

A moins que l'ont peut faire un tableau de structure avec attribute packet, mais je ne sais pas faire.

En fait ma question principale c'est comment modifier 3 bit ou 4 bit qui se trouve au milieu
d'un word 16bit.
les bits 4,5,6 et 12,13,14,15

on peut faire un tableau de structures bien sûr, c'est juste un type comme un autre.

avec la structure de champ de bits vous feriez

struct __attribute__((packed)) Attributs {
  uint16_t typeset : 3;      // Bits 0-2
  uint16_t dw : 1;           // Bit 3
  uint16_t conceal : 1;      // Bit 4
  uint16_t dh : 1;           // Bit 5
  uint16_t insert : 1;       // Bit 6
  uint16_t inverse : 1;      // Bit 7
  uint16_t foreground : 2;   // Bits 8-9
  uint16_t flash : 1;        // Bit 10
  uint16_t background : 4;   // Bits 12-15
} ;

Attributs attributs[25] ;

void prinlntBits(uint16_t value, uint8_t numBits) {
  for (int8_t i = numBits - 1; i >= 0; i--) Serial.write(bitRead(value, i) ? '1' : '0');
  Serial.println();
}

void printAttributs(const Attributs &attribut) {
  Serial.print("typeset: ");    prinlntBits(attribut.typeset, 3);
  Serial.print("dw: ");         prinlntBits(attribut.dw, 1);
  Serial.print("conceal: ");    prinlntBits(attribut.conceal, 1);
  Serial.print("dh: ");         prinlntBits(attribut.dh, 1);
  Serial.print("insert: ");     prinlntBits(attribut.insert, 1);
  Serial.print("inverse: ");    prinlntBits(attribut.inverse, 1);
  Serial.print("foreground: "); prinlntBits(attribut.foreground, 2);
  Serial.print("flash: ");      prinlntBits(attribut.flash, 1);
  Serial.print("background: "); prinlntBits(attribut.background, 4);
}

void definirAttributs(Attributs &attribut, uint8_t typeset, uint8_t dw, uint8_t conceal, uint8_t dh, uint8_t insert, uint8_t inverse, uint8_t foreground, uint8_t flash, uint8_t background) {
  attribut.typeset = typeset;       // Bits 0-2
  attribut.dw = dw;                 // Bit 3
  attribut.conceal = conceal;       // Bit 4
  attribut.dh = dh;                 // Bit 5
  attribut.insert = insert;         // Bit 6
  attribut.inverse = inverse;       // Bit 7
  attribut.foreground = foreground; // Bits 8-9
  attribut.flash = flash;           // Bit 10
  attribut.background = background; // Bits 12-15
}

void setup() {
  Serial.begin(115200);
  definirAttributs(attributs[5], 0b101, 0b0, 0b1, 0b1, 0b1, 0b0, 0b11, 0b0, 0b1011);
  printAttributs(attributs[5]);
}

void loop() {}

➜ vous pouvez tester ici

vous verrez qu'en sortie on a bien ce que l'on a demandé pour chaque champ

typeset: 101
dw: 0
conceal: 1
dh: 1
insert: 1
inverse: 0
foreground: 11
flash: 0
background: 1011

et si vous voulez les 16 bits comme un uint16_t pour être en règle avec la norme C++ (il faut lire des trucs sur le type punning en C++), il faut faire un memcpy() et le compilateur comprendra

une fonction comme cela vous donnera le bon type uint16_t

inline uint16_t extraireAttributs(const Attributs &attribut) {
  uint16_t value;
  memcpy(&value, &attribut, sizeof(uint16_t));
  return value;
}

(en la mettant inline, il y a de grandes chances que le compilateur ne fasse rien du tout et vous laisse utiliser vraiment les bits de la structure mais il aura compris que le type a bien été changé).

Dans mon application je ne pense pas avoir besoin des 16 bits, c'est surtout les champs.
J'ai inversé le tableau comme indiqué sur le schéma, si je ne me trompe pas le bit 0 est le premier champs.

void definirAttributs(Attributs &attribut, uint8_t typeset, uint8_t dw, uint8_t conceal, uint8_t dh, uint8_t insert, uint8_t inverse, uint8_t foreground, uint8_t flash, uint8_t background) {
  attribut.background = background; // Bits 0-2
  attribut.flash = flash;           // Bit 3
  attribut.foreground = foreground; // Bits 4-6
  attribut.inverse = inverse;       // Bit 7
  attribut.insert = insert;         // Bit 8
  attribut.dh = dh;                 // Bit 9
  attribut.conceal = conceal;       // Bit 10
  attribut.dw = dw;                 // Bit 11  
  attribut.typeset = typeset;       // Bits 12-15
}

Pour la définitions des attributs, comme j'utilise des variables uint8_t je devrais faire ceci au lieu du binaire


> definirAttributs(attributs[5], background & 7, flash & 1,  foreground & 7,  inverse & 1, insert & 1, dh & 1, conceal & 1, dw & 1, typeset & 7);


donc pour recupérer une valeur ca donnera ceci:
attributs[5].background par exemple ?
ou
int value = attributs[5].background & 7;

Merci pour ce code tres propre et dont j'ai appris beaucoup de choses.

Juste une question , concernant les structure de bit.
Le 1er champ correspond au plus haut bit ? c'est a dire dans ce cas le bit 15 ? ou est ce que ca commence au bit 0 ?

et dans la fonction definirAttributs, les emplacement de parametres n'ont pas d'importance ?
je veux dire que je peut metre dans n'importe quel ordre les paramèetres, pas forcément commencer au premier champ = 1er paramètre ?

Le code proposé par @J-M-L est bien commenté il me semble.

On peut affecter les valeurs dans n'importe quel ordre. C'est le nom du champs qui permet de placer la valeur au bon endroit.

J'ai testé ca ne fonctionne pas, il met des 0 ou il n'y en a pas, les valeurs sont inversés, j'ai du apporter des modifications.

La structure est inversé, le premier champ occupe 0-2 et commence par background,
J'ai modifié le print du résultat pour un affichage en decimal car valeur max est 7,

Les paramètres ce ne sont pas du binaire mais des uint8_t, ces données proviennent d'un port série.

ca donne ceci avec le résultat faussé:

struct __attribute__((packed)) Attributs {
  uint16_t background : 3;      // Bits 0-2
  uint16_t flash : 1;        // Bit 1
  uint16_t foreground : 3;   // Bits 4-6
  uint16_t inverse : 1;      // Bit 7
  uint16_t insert : 1;       // Bit 8
  uint16_t dh : 1;           // Bit 9
  uint16_t conceal : 1;      // Bit 10
  uint16_t dw : 1;           // Bit 11
  uint16_t typeset : 4;      // Bits 12-15
} ;
void printAttributs(const Attributs &attribut) {
  Serial.printf("\r\n\r\ntypeset: %d\r\n", attribut.typeset);    
  Serial.printf("dw: %d\r\n", attribut.dw);         
  Serial.printf("conceal: %d\r\n", attribut.conceal);    
  Serial.printf("dh: %d\r\n", attribut.dh);         
  Serial.printf("insert: %d\r\n", attribut.insert);     
  Serial.printf("inverse: %d\r\n", attribut.inverse);    
  Serial.printf("foreground: %d\r\n", attribut.foreground); 
  Serial.printf("flash: %d\r\n", attribut.flash);      
  Serial.printf("background: %d\r\n", attribut.background); 
}

dans le setup:

uint8_t typeset = 2;
  uint8_t dw = 1;
  uint8_t conceal = 1;
  uint8_t dh = 1;
  uint8_t insert = 1;
  uint8_t inverse = 1;
  uint8_t foreground = 2;
  uint8_t flash = 1;
  uint8_t background = 7;

  definirAttributs(attributs[5], background & 7, flash & 1,  foreground & 7,  inverse & 1, insert & 1, dh & 1, conceal & 1, dw & 1, typeset & 7);  
  printAttributs(attributs[5]); 
  foreground = 4;
  inverse = 0;
  definirAttributs(attributs[5], background & 7, flash & 1,  foreground & 7,  inverse & 1, insert & 1, dh & 1, conceal & 1, dw & 1, typeset & 7);
  printAttributs(attributs[5]); 
  typeset = 2;
  definirAttributs(attributs[5], background & 7, flash & 1,  foreground & 7,  inverse & 1, insert & 1, dh & 1, conceal & 1, dw & 1, typeset & 7);  
  printAttributs(attributs[5]);

Résultat:

 typeset: 7
dw: 1
conceal: 0
dh: 1
insert: 1
inverse: 1
foreground: 1
flash: 1
background: 2


typeset: 7
dw: 1
conceal: 0
dh: 0
insert: 1
inverse: 1
foreground: 1
flash: 1
background: 2


typeset: 7
dw: 1
conceal: 0
dh: 0
insert: 1
inverse: 1
foreground: 1
flash: 1
background: 2

C'est peut être du au printf ou un alignement ou autre:
les valeurs de typeset et background sont inversés,
background doit être à 7
typeset à 2
foreground a 2

puis apres foreground passe a 4 et inverse à 0
puis typeset toujours à 2

J'ai oublié ce code:

void definirAttributs(Attributs &attribut, uint8_t typeset, uint8_t dw, uint8_t conceal, uint8_t dh, uint8_t insert, uint8_t inverse, uint8_t foreground, uint8_t flash, uint8_t background) {
  attribut.background = background; // Bits 0-2
  attribut.flash = flash;           // Bit 3
  attribut.foreground = foreground; // Bits 4-6
  attribut.inverse = inverse;       // Bit 7
  attribut.insert = insert;         // Bit 8
  attribut.dh = dh;                 // Bit 9
  attribut.conceal = conceal;       // Bit 10
  attribut.dw = dw;                 // Bit 11  
  attribut.typeset = typeset;       // Bits 12-15
}

Ce serait mieux si tu donnais le code complet au lieu de petits bouts.

pour le parametre typeset, j'ai modifié car je faisait typeset & 7 alors que c'est typeset & 0xF,mais ca na rien changé.
Je met le code mais il y beaucoup de code en commentaire pour test.

////////////////////////////////////////////////////////////////////////

// DEBUT DU PROGRAMME

////////////////////////////////////////////////////////////////////////


/*enum CONTEXT {
    BACKGROUND = 0,
    FLASH,
    FOREGROUND,
    INVERSE,
    INSERT,
    DOUBLEHEIGHT,
    MASQUE,
    DOUBLEWIDTH,    
    TYPEANDSET
};*/

//static uint16_t buf_attr[25];

/*struct __attribute__((packed)) Attributs {
  uint16_t background : 3;      // Bits 0-2
  uint16_t flash : 1;        // Bit 1
  uint16_t foreground : 3;   // Bits 4-6
  uint16_t inverse : 1;      // Bit 7
  uint16_t insert : 1;       // Bit 8
  uint16_t dh : 1;           // Bit 9
  uint16_t conceal : 1;      // Bit 10
  uint16_t dw : 1;           // Bit 11
  uint16_t typeset : 4;      // Bits 12-15
} ;*/

struct __attribute__((packed)) Attributs {
  uint16_t typeset : 4;      // Bits 12-15
  uint16_t dw : 1;           // Bit 11
  uint16_t conceal : 1;      // Bit 10
  uint16_t dh : 1;           // Bit 9
  uint16_t insert : 1;       // Bit 8
  uint16_t inverse : 1;      // Bit 7
  uint16_t foreground : 3;   // Bits 4-6
  uint16_t flash : 1;        // Bit 3
  uint16_t background : 3;   // Bits 0-2
} ;

Attributs attributs[25] ;


//static uint16_t save_code_attr = 0;
////////////////////////////////////////////////////////////////////////

void setup() {
  //Serial2.begin(1200, SERIAL_7E1, 17, 16);
  // Le premier port série matériel de l'ATMega (Serial / RXD0 TXD0)
  // ou de l'ESP32 (Serial / U0RXD U0TXD) est utilisé pour la connexion
  // avec le PC.
  Serial.begin(115200);

  uint8_t typeset = 2;
  uint8_t dw = 1;
  uint8_t conceal = 1;
  uint8_t dh = 1;
  uint8_t insert = 1;
  uint8_t inverse = 1;
  uint8_t foreground = 2;
  uint8_t flash = 1;
  uint8_t background = 7;

  definirAttributs(attributs[5], typeset & 0xF,  dw & 1, conceal & 1, dh & 1, insert & 1,  inverse & 1, foreground & 7, flash & 1,  background & 7);  
  printAttributs(attributs[5]); 
  foreground = 4;
  inverse = 0;
  definirAttributs(attributs[5], typeset & 0xF,  dw & 1, conceal & 1, dh & 1, insert & 1,  inverse & 1, foreground & 7, flash & 1,  background & 7);
  printAttributs(attributs[5]);
  typeset = 5;
  definirAttributs(attributs[5], typeset & 0xF,  dw & 1, conceal & 1, dh & 1, insert & 1,  inverse & 1, foreground & 7, flash & 1,  background & 7);  
  printAttributs(attributs[5]); 

  /*uint8_t typeset = 2;
  uint8_t dw = 1;
  uint8_t conceal = 1;
  uint8_t dh = 1;
  uint8_t insert = 1;
  uint8_t inverse = 1;
  uint8_t foreground = 2;
  uint8_t flash = 1;
  uint8_t background = 7;

  saveContext(&typeset, &dw, &conceal, &dh, &insert, &inverse, &foreground, &flash, &background);
  foreground = 4;
  inverse = 0;
  saveContext(nullptr, nullptr, nullptr, nullptr, nullptr, &inverse, &foreground, nullptr, &background);
  typeset = 4;
  saveContext(&typeset, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);

  Serial.printf("\r\n\r\ntypeset = %d\r\n", readContext(TYPEANDSET));
  Serial.printf("double width = %d\r\n", readContext(DOUBLEWIDTH));
  Serial.printf("Conceal = %d\r\n", readContext(MASQUE));
  Serial.printf("double height = %d\r\n", readContext(DOUBLEHEIGHT));
  Serial.printf("insert = %d\r\n", readContext(INSERT));
  Serial.printf("inverse = %d\r\n", readContext(INVERSE));
  Serial.printf("foreground = %d\r\n", readContext(FOREGROUND));
  Serial.printf("flash = %d\r\n", readContext(FLASH));
  Serial.printf("background = %d\r\n", readContext(BACKGROUND));
  Serial.printf("buf_attr[5] = 0x%04X\r\n", buf_attr[5]);*/
  
}

void prinlntBits(uint16_t value, uint8_t numBits) {
  for (int8_t i = numBits - 1; i >= 0; i--) Serial.write(bitRead(value, i) ? '1' : '0');
  Serial.println();
  Serial.println();
}

void printAttributs(const Attributs &attribut) {
  Serial.printf("\r\n\r\ntypeset: %d\r\n", attribut.typeset);    
  Serial.printf("dw: %d\r\n", attribut.dw);         
  Serial.printf("conceal: %d\r\n", attribut.conceal);    
  Serial.printf("dh: %d\r\n", attribut.dh);         
  Serial.printf("insert: %d\r\n", attribut.insert);     
  Serial.printf("inverse: %d\r\n", attribut.inverse);    
  Serial.printf("foreground: %d\r\n", attribut.foreground); 
  Serial.printf("flash: %d\r\n", attribut.flash);      
  Serial.printf("background: %d\r\n", attribut.background); 
}

/*void printAttributs(const Attributs &attribut) {
  Serial.print("typeset: ");    prinlntBits(attribut.typeset, 3);
  Serial.print("dw: ");         prinlntBits(attribut.dw, 1);
  Serial.print("conceal: ");    prinlntBits(attribut.conceal, 1);
  Serial.print("dh: ");         prinlntBits(attribut.dh, 1);
  Serial.print("insert: ");     prinlntBits(attribut.insert, 1);
  Serial.print("inverse: ");    prinlntBits(attribut.inverse, 1);
  Serial.print("foreground: "); prinlntBits(attribut.foreground, 2);
  Serial.print("flash: ");      prinlntBits(attribut.flash, 1);
  Serial.print("background: "); prinlntBits(attribut.background, 4);
}*/

void definirAttributs(Attributs &attribut, uint8_t typeset, uint8_t dw, uint8_t conceal, uint8_t dh, uint8_t insert, uint8_t inverse, uint8_t foreground, uint8_t flash, uint8_t background) {
  attribut.background = background; // Bits 0-2
  attribut.flash = flash;           // Bit 3
  attribut.foreground = foreground; // Bits 4-6
  attribut.inverse = inverse;       // Bit 7
  attribut.insert = insert;         // Bit 8
  attribut.dh = dh;                 // Bit 9
  attribut.conceal = conceal;       // Bit 10
  attribut.dw = dw;                 // Bit 11  
  attribut.typeset = typeset;       // Bits 12-15
}

/*uint8_t readContext(CONTEXT ctx)
{
    uint8_t value = 0;    
    //uint8_t line = getCursorY();
    uint16_t codeAttr = buf_attr[5];

    switch(ctx) {
      case BACKGROUND: value = codeAttr & 0x07; break;
      case FLASH: value = bitRead(codeAttr, 3); break;
      case FOREGROUND: value = (codeAttr >> 4) & 7; break;
      case INVERSE: value = bitRead(codeAttr, 7); break;
      case INSERT: value = bitRead(codeAttr, 8); break;
      case DOUBLEHEIGHT: value = bitRead(codeAttr, 9); break;
      case MASQUE: value = bitRead(codeAttr, 10); break;
      case DOUBLEWIDTH: value = bitRead(codeAttr, 11); break;
      case TYPEANDSET: value = (codeAttr >> 12) & 0xF; break;

    }
    return value;
}

void saveContext(uint8_t *typeSet, uint8_t *doubleWidth, uint8_t *masque,uint8_t *doubleHeight,uint8_t *insert,uint8_t *inverse,uint8_t *fg_color, uint8_t *blink,uint8_t *bg_color)
{      
  
  //uint16_t code_attr = buf_attr[5];
  
  if(bg_color != nullptr) {    
    buf_attr[5] |= ((buf_attr[5] & 7) | (*bg_color & 7));
  }    // backgroune color

  if (blink != nullptr) {
     if (*blink & 1) buf_attr[5] |= (1 << 3); else buf_attr[5] &= ~(1 << 3); //bitSet(buf_attr[5], 3); else bitClear(buf_attr[5], 3); 
  }   // blink 

  if (fg_color != nullptr) 
  {
    buf_attr[5] |=  ((buf_attr[5] & ( 0 << 4)) | ((*fg_color & 7) << 4));
  }                                     //Foregrounf color

  if(inverse != nullptr) { 
    if (*inverse & 1) bitSet(buf_attr[5], 7); else bitClear(buf_attr[5], 7); 
  }        // inverse

  if(insert != nullptr) { 
    if (*insert & 1) bitSet(buf_attr[5], 8); else bitClear(buf_attr[5], 8); 
  }         // insert

  if(doubleHeight != nullptr) { 
    if (*doubleHeight & 1) bitSet(buf_attr[5], 9); else bitClear(buf_attr[5], 9); 
  }   // double height

  if(masque != nullptr) { 
    if( *masque & 1) bitSet(buf_attr[5], 10); else bitClear(buf_attr[5], 10); 
  }       // masquage (Conceal)

  if(doubleWidth != nullptr) { 
    if (*doubleWidth & 1) bitSet(buf_attr[5], 11); else bitClear(buf_attr[5], 11); 
  }  // double width

  if (typeSet != nullptr) {
    //buf_attr[5] |= (*typeSet & 7) << 12;
    buf_attr[5] |=  ((buf_attr[5] & ( 7 << 12)) | ((*typeSet & 0xF) << 12));
  }                                         // type set
  
  //buf_attr[5] = code_attr;
 
  Serial.printf("\r\n\r\nTypeset: %d\r\n", (buf_attr[5] >> 12) & 0xF);                   // type set
  Serial.printf("Double width: %d\r\n", bitRead(buf_attr[5], 11));               // double width
  Serial.printf("Conceal: %d\r\n", bitRead(buf_attr[5], 10));                    // madquage
  Serial.printf("Double height: %d\r\n", bitRead(buf_attr[5], 9));               // double height
  Serial.printf("Insert: %d\r\n", bitRead(buf_attr[5], 8));                      // insert
  Serial.printf("Inverse: %d\r\n", bitRead(buf_attr[5], 7));                     // inverse
  Serial.printf("Foreground: %d\r\n", (buf_attr[5] >> 4) & 7);                   // Foreground
  Serial.printf("Flash: %d\r\n", bitRead(buf_attr[5], 3));                      // blink
  Serial.printf("Background: %d\r\n\r\n", buf_attr[5] & 0x07);                   // Background

  Serial.print(buf_attr[5], HEX);
  Serial.printf("\r\nbuf_attr[5] = 0x%04X\r\n", buf_attr[5]);
}*/

/*void saveContext(uint8_t typeSet, uint8_t doubleWidth, uint8_t masque,uint8_t doubleHeight,uint8_t insert,uint8_t inverse,uint8_t fg_color, uint8_t blink,uint8_t bg_color)
{
  uint16_t code_attr;
  code_attr = 0;

  code_attr = bg_color & 7;                                                   // backgroune color 
  if (blink & 1) bitSet(code_attr, 3); else bitClear(code_attr, 3);           // blink
  code_attr |=  (fg_color & 7) << 4 ;                                         //Foregrounf color
  
  if (inverse & 1) bitSet(code_attr, 7); else bitClear(code_attr, 7);         // inverse
  if (insert & 1) bitSet(code_attr, 8); else bitClear(code_attr, 8);          // insert
  if (doubleHeight & 1) bitSet(code_attr, 9); else bitClear(code_attr, 9);    // double height
  if( masque & 1) bitSet(code_attr, 10); else bitClear(code_attr, 10);        // masquage (Conceal)
  if (doubleWidth & 1) bitSet(code_attr, 11); else bitClear(code_attr, 11);   // double width

  code_attr |= (typeSet & 7) << 12;                                           // type set
  
  code_attr = code_attr;

  Serial.printf("\r\n\r\nTypeset: %d\r\n", (code_attr >> 12) & 0xF);                   // type set
  Serial.printf("Double width: %d\r\n", bitRead(code_attr, 11));               // double width
  Serial.printf("Conceal: %d\r\n", bitRead(code_attr, 10));                    // madquage
  Serial.printf("Double height: %d\r\n", bitRead(code_attr, 9));               // double height
  Serial.printf("Insert: %d\r\n", bitRead(code_attr, 8));                      // insert
  Serial.printf("Inverse: %d\r\n", bitRead(code_attr, 7));                     // inverse
  Serial.printf("Foreground: %d\r\n", (code_attr >> 4) & 7);                   // Foreground
  Serial.printf("Insert: %d\r\n", bitRead(code_attr, 3));                      // blink
  Serial.printf("Background: %d\r\n\r\n", code_attr & 0x07);                   // Background

  Serial.print(code_attr, HEX);
  Serial.printf("\r\ncode_attr = %04X\r\n", code_attr);
}*/

/*void saveContext(uint8_t *typeSet, uint8_t *doubleWidth, uint8_t *masque,uint8_t *doubleHeight,uint8_t *insert,uint8_t *inverse,uint8_t *fg_color, uint8_t *blink,uint8_t *bg_color)
{      

  if(bg_color != nullptr) {
    buf_attr[5] = *bg_color & 7;
  }    // backgroune color
  if (blink != nullptr) {
     if (*blink & 1) bitSet(buf_attr[5], 3); else bitClear(buf_attr[5], 3); 
  }   // blink                                                          
  if (fg_color != nullptr) 
  {
    buf_attr[5] |=  (*fg_color & 7) << 4 ;
  }                                     //Foregrounf color
  if(inverse != nullptr) { 
    if (*inverse & 1) bitSet(buf_attr[5], 7); else bitClear(buf_attr[5], 7); 
  }        // inverse
  if(insert != nullptr) { 
    if (*insert & 1) bitSet(buf_attr[5], 8); else bitClear(buf_attr[5], 8); 
  }          // insert
  if(doubleHeight != nullptr) { 
    if (*doubleHeight & 1) bitSet(buf_attr[5], 9); else bitClear(buf_attr[5], 9); 
  }   // double height
  if(masque != nullptr) { 
    if( *masque & 1) bitSet(buf_attr[5], 10); else bitClear(buf_attr[5], 10); 
  }       // masquage (Conceal)
  if(doubleWidth != nullptr) { 
    if (*doubleWidth & 1) bitSet(buf_attr[5], 11); else bitClear(buf_attr[5], 11); 
  }  // double width
  if (typeSet != nullptr) {
    buf_attr[5] |= (*typeSet & 7) << 12;
  }                                         // type set
  

  Serial.printf("\r\n\r\nTypeset: %d\r\n", (buf_attr[5] >> 12) & 0xF);                   // type set
  Serial.printf("Double width: %d\r\n", bitRead(buf_attr[5], 11));               // double width
  Serial.printf("Conceal: %d\r\n", bitRead(buf_attr[5], 10));                    // madquage
  Serial.printf("Double height: %d\r\n", bitRead(buf_attr[5], 9));               // double height
  Serial.printf("Insert: %d\r\n", bitRead(buf_attr[5], 8));                      // insert
  Serial.printf("Inverse: %d\r\n", bitRead(buf_attr[5], 7));                     // inverse
  Serial.printf("Foreground: %d\r\n", (buf_attr[5] >> 4) & 7);                   // Foreground
  Serial.printf("Insert: %d\r\n", bitRead(buf_attr[5], 3));                      // blink
  Serial.printf("Background: %d\r\n\r\n", buf_attr[5] & 0x07);                   // Background

  Serial.print(buf_attr[5], HEX);
  Serial.printf("\r\nbuf_attr[5] = 0x%04X\r\n", buf_attr[5]);*/

/*  Serial.printf("\r\n\r\nTypeset: %d\r\n", (code_attr >> 12) & 0xF);                   // type set
  Serial.printf("Double width: %d\r\n", bitRead(code_attr, 11));               // double width
  Serial.printf("Conceal: %d\r\n", bitRead(code_attr, 10));                    // madquage
  Serial.printf("Double height: %d\r\n", bitRead(code_attr, 9));               // double height
  Serial.printf("Insert: %d\r\n", bitRead(code_attr, 8));                      // insert
  Serial.printf("Inverse: %d\r\n", bitRead(code_attr, 7));                     // inverse
  Serial.printf("Foreground: %d\r\n", (code_attr >> 4) & 7);                   // Foreground
  Serial.printf("Insert: %d\r\n", bitRead(code_attr, 3));                      // blink
  Serial.printf("Background: %d\r\n\r\n", code_attr & 0x07);                   // Background

  Serial.print(code_attr, HEX);
  Serial.printf("\r\ncode_attr = 0x%04X\r\n", code_attr);*/
//}


////////////////////////////////////////////////////////////////////////

void loop() {
 
}


////////////////////////////////////////////////////////////////////////

sur trois articles différents il est mentionné que ca fonctionne avec des types intou unsigned int .
peut etre qu'avec uint16_t ca ne fonctionne pas ?