[resolu] Du code ascii dans une chaîne de caractères

Salut les amis,

Toujours en train de jouer avec mon minitel, je voudrais me simplifier la vie en insérant des codes dans mes chaines de caractères.

Par exemple, pour lui faire afficher "Accélération", je dois lui envoyer ça :

  Serial.print (F("Acc"));     // envoyer "Acc"
  Serial.write(m_SS2);       // envoyer 0x19 (passage en jeu étendu)
  Serial.write(0x42);          // envoyer 0x42 (accent aigu)
  Serial.print(F("el"));         // envoyer "el"
  Serial.write(m_SS2);       // envoyer 0x19 (passage en jeu étendu)
  Serial.write(0x42);          // envoyer 0x42 (accent aigu)
  Serial.print(F("eration ")); // envoyer "eration"

Ca marche, mais c'est bien long. Oui, en minitel, il faut écrire l'accent, puis la voyelle à accentuer. J'ai donc essayé ça :

  Serial.print (F("Acc\x19\x42el\x19\x42eration "));

Il affiche "Acclration" (remplacer les * par des flèches). Alors je regarde, et c'est comme s'il avait interprété (0x19, 0x2E) qui est justement la séquence pour afficher une flèche...

J'ai donc envoyé :

  Serial.print (F("Acc\x19\x42dl\x19\x42eration "));  // le premier 'e' est remplacé par un 'd'

Bim, il m'affiche "Acc#l*ration", où # est la flèche (0x19, 0x2D)

J'ai alors envoyé :

  Serial.print (F("Acc\x19\x442el\x19\x442eration "));  // en pensant que le premier 4 est passé à la trappe.

Il m'affiche toujours "Acclration".

J'ai essayé sans le F(),

  Serial.print ("Acc\x19\x42el\x19\x42eration ");

Ca ne change rien.

Réflexion intime : est-ce que le compilateur n'interpréterait pas \0x42e comme un code, 'e' faisant partie des chiffres hexa... En le passant en 8 bits, alors il ne reste plus que 0x2e.

J'ai alors essayé ceci :

  Serial.print (F("Acc\x19\66el\x19\66eration "));  // en remplaçant 0x42 par 66 (décimal)

la réponse du minitel : "Acc_el_eration". sachant que pour le minitel, afficher un '_' correspond à dire qu'il y a une erreur dans le code étendu (caractère inconnu). Donc le 66 n'est pas bien passé...

Bon, quelqu'un a-t-il la recette magique du \ et du format des codes? La plus étonnant est que le \0x19 semble bien passer, mais pas la suite...

Merci à vous :wink:

C'est bien ça, tant qu'on est dans l'hexa, le code sera pris tel qu'écrit. En gors, \x42e est pris pour 0x42E, soit 2E.

J'ai essayé la séquence "\x19\x48e" qui devrait afficher 'ë', et bien il l'a pris pour "\x19\x0e" (la liaison est en 7 bits, donc 0x8e devient 0x0e).

J'ai donc essayé ça, qui devrait afficher "Accülôration" :

  Serial.print (F("Acc\x19\x48ul\x19\x43oration "));

Et ça marche, puisque 'u' et 'o' ne sont pas de l'hexa...

Alors comment puis-je faire? écrire "\x19\x42;e"? (marche pas). Il doit bien exister un séparateur, non? J'ai lu "passer en octal", mais comment fait-on? "\031\0102" ne passe pas.

Mes recherches sur le net sont vaines, car je connais pas le nom précis des \n, \0, et autres du C...

EDIT :

  Serial.print (F("Acc\x19\x42\x65l\x19\x42\x65ration "));

fonctionne, puisque j'envoie (0x19, 0x42) : accent aigu, puis (0x65) : 'e'. mais du coup, c'est âchement moins lisible...

pepe:
Pour \66, il est interprété comme un code en octal, soit 066, ce qui donne 0x36 correspondant au caractère '6'.

Les codes explicites de caractères peuvent être donnés en hexadécimal ou en octal, mais pas en décimal.

Yes! merci pour l'info! donc si j'envoie "Acc\31\102el\31\102eration", ça doit passer? (la flemme de rebrancher le biniou ce soir, on verra demain). Il restera le problème si je compte écrire un caractère "étendu" juste avant un chiffre, ce chiffre sera englobé dans le code octal...

N'oublions pas que le minitel date des années 80, et qu'ils ne pensaient certainement pas que des gens continueraient à jouer avec plus de 30 ans après... Il est logique que certaines incompatibilités apparaissent...

Je considère la chose résolue!

Cinci.

pepe:
Pour simplifier l'écriture du programme, tu pourrais définir les séquences correspondant aux caractères spéciaux. Par exemple :

#define e_aigu "\x19\x42""e"

puis :

Serial.print (F("Acc" e_aigu "l" e_aigu "ration "));

pas bête! merci encore!

Pour info, en passant de ça :

  Serial.print (F("Acc"));
  Serial.write(m_SS2);
  Serial.write(0x42);  // accent aigû
  Serial.print(F("el"));
  Serial.write(m_SS2);
  Serial.write(0x42);  // accent aigû
  Serial.print(F("eration "));

à ça :

  Serial.print (F("Acc\x19\x42" "el\x19\x42" "eration "));

j'ai économisé 54 octets de flash. Vu le nombre de trucs que j'écris, ça devrait être plus que bénéfique au final!

Déjà que j'ai découvert hier le F(), qui m'a fait passer de 1153 octets de RAM à 651...

si tu as des messages qui se répètent à plusieurs endroits de ton programme, mieux que F() il faut les stocker dans des chaines progmem et ensuite n'appeler que l'adresse de la chaine.

avec F() c'est bien du progmen mais si tu utilises plusieurs fois la même chaine, elle est quand même stockée plusieurs fois (en flash et non en ram, c'est la magie de progmem) donc tu perds tout de même de la place betement

Je n'utilise jamais deux fois la même chaîne, donc j'ai tout mis partout des F().

Et avec la combine de pepe, (#define e_aigu "\x19\x42" "e"), j'ai encore gagné 612 octets en flash (sans compter la rapidité d'exécution, mais comme la liaison série est à 4800 bds, ça ne change pas grand chose, le buffer d'émission est vite saturé...)

Pourtant, je n'ai qu'un simple menu de 15 lignes sur un écran 40x25... Mais le code complet occupe 16644 en flash pour 1812 linges de code

OK, je gère le Minitel ,un LCD 16x2, deux BP, 4 leds et un moteur PAP (avec accélération linéaire et gestion courant du driver), le tout en "multitâche" (plusieurs boucles while et for en parallèle) et pas mal d'interruptions. Dans un petit UNO.

Je gagnerais encore beaucoup en virant cette vilaine lib LCD qui utilise delay() et digitalwrite(), mais je n'ai pas encore travaillé sur le sujet LCD. Maintenant que le côté terminal-Minitel prend forme, je vais vite me passer du LCD!

Super_Cinci:
Je n'utilise jamais deux fois la même chaîne, donc j'ai tout mis partout des F().

Et avec la combine de pepe, (#define e_aigu "\x19\x42" "e"), j'ai encore gagné 612 octets en flash (sans compter la rapidité d'exécution, mais comme la liaison série est à 4800 bds, ça ne change pas grand chose, le buffer d'émission est vite saturé...)

Pourtant, je n'ai qu'un simple menu de 15 lignes sur un écran 40x25... Mais le code complet occupe 16644 en flash pour 1812 linges de code

OK, je gère le Minitel ,un LCD 16x2, deux BP, 4 leds et un moteur PAP (avec accélération linéaire et gestion courant du driver), le tout en "multitâche" (plusieurs boucles while et for en parallèle) et pas mal d'interruptions. Dans un petit UNO.

Je gagnerais encore beaucoup en virant cette vilaine lib LCD qui utilise delay() et digitalwrite(), mais je n'ai pas encore travaillé sur le sujet LCD. Maintenant que le côté terminal-Minitel prend forme, je vais vite me passer du LCD!

bonsoir bricofoy
j'ai un peu suivi ton topic "minitel"
juste pour etre ""sur" 8)

tu interface "directement" ton M1B vers arduino au travers de la DIn5 ?

Alors moi, oui, j'ai branché le Rx/Tx dessus, une pullup entre 2 et 8 k sur le Rx de l'arduino, un Serial.begin(1200, SERIAL7E1); et roule ma poule, tout devient possible (le Minitel utilise des niveaux TTL). On a même une alim de 12V/1A sur la DIN5, si c'est pas royal!

Par contre, il faut imprimer le STUM1B des PTT (200 pages, téléchargeable partout, c'est libre), et en faire son livre de chevet pendant 3 semaines pour enfin comprendre comment ça fonctionne là-dedans (tout n'es pas dit, bien sûr)... Une autre broche (PT) sur la DIN peut avoir son effet, mais je n'ai pas encore joué avec, j'ai donc fait l'impasse sur le sujet.