Switch Case sur suite binaire

Bonjour je suis actuellement en projet de 3ème année à la fac, je code une radio avec un module AD9850, le but de base est de faire de la modulation de fréquence 8 FSK (Code OLIVIA en radioamateur) Mais pour avancer à mon rythme je suis passé par plusieurs étapes, j'ai dans un premier temps réalisé un programme pour faire une modulation RTTY, et je suis maintenant en train d'essayer de faire du CONTESTIA.

Je ne vais pas rentrer dans les détails, s'il y a des questions je répondrais en dessous.

Concrètement, le problème que j'ai actuellement :

Je demande une suite de texte dans la console que je stocke dans un tableau, je convertis ensuite ce tableau en suite binaire, je me retrouve alors avec une suite binaire du code ascii (sur 8 bits) et j'aimerais maintenant trier les bits par paquets de 3 en leur attribuant une variable.

Je m'explique,

Prenons par exemple AB : 0100000101000010

J'aimerais créer 8 conditions qui sont les suivantes :

000 = f0
001 = f0+Δf
010 = f0+2Δf
...
111 = f0+7Δf

Et j'aimerais comparer dans l'ordre mon tableau avec ces conditions, par exemple 0100000101000010 je commence avec les 3 premiers bit et je dit que 010 = f0+2Δf et je stocke tout ça dans un nouveau tableau et ainsi de suite avec tout les autres.

Tout ceci me permettra de moduler en fréquence chaque paquet de 3 bits pour les émettre, pour la partie émission je devrais me débrouiller, j'aimerais juste savoir comment transformer ma suite binaire en paquet de 3 bits associés à des variables, le tout dans des tableaux.

Je ne me rend pas trop compte de la difficulté de cela et si quelqu'un pourra m'aider, mais voici le code que j'ai pour le moment :

#include "EF_AD9850.h"
#include <stdint.h>


/*Transmission paramèteres*/
/*----------------------------------------------------------------------*/
float FREQ;
#define OFFSET 31.25
/*----------------------------------------------------------------------*/


/*AD9850 - Branchements Arduino*/
/*----------------------------------------------------------------------*/
//CLK - D11, FQ - D10, DATA - D9, RST - D8
#define CLK  11
#define FQ   10
#define DATA 9
#define RST  8
/*----------------------------------------------------------------------*/

/*Tableau chaîne de caractères*/
/*----------------------------------------------------------------------*/
char message[200];
/*----------------------------------------------------------------------*/


/*AD9850 - Définition des ports*/
/*----------------------------------------------------------------------*/
EF_AD9850 AD9850(CLK, FQ, DATA, RST);
/*----------------------------------------------------------------------*/



void setup()
{
  
/*AD9850 - Initialisation et initialisation moniteur série*/
/*----------------------------------------------------------------------*/
  AD9850.init();
  AD9850.reset();
  Serial.begin(9600);
/*----------------------------------------------------------------------*/

  
/*AD9850 - Configuration de la fréquence*/
/*----------------------------------------------------------------------*/
  Serial.println("Quel est votre fréquence ?");
  while (Serial.available() == 0) {
    ;
  }
  FREQ = Serial.parseFloat();
  Serial.print("Votre fréquence est : "); Serial.println(FREQ);
/*----------------------------------------------------------------------*/      

}

 
void loop()
{

/*Demande chaîne de caractères ascii et conversion en binaire*/
/*----------------------------------------------------------------------*/

  while(Serial.available() != 0)
  {
    (void)Serial.read(); //remove Newline charcater from buffer
  }
  Serial.println("Quel est votre message ?");
  while (Serial.available() == 0)
  {
    ;
  }
  byte m = Serial.readBytesUntil('\n', message, 200);
  message[m] = '\0';  //insert null-charcater
  Serial.print("Le message transmis est : "); Serial.println(message);
  Serial.println();
  Serial.println(" En binaire : ");
  for (int i=0;i<strlen(message);i++)  // loop through all chars in string (from 'first letter' to 'last letter')
  {
    for (int j=7;j>=0;j--) // loop from bit-7 down to bit-0 (high-bit to low-bit)
      Serial.print(bitRead(message[i],j)); // from message[i] read the bit-j and print it
  }
  Serial.println();

Merci par avance

Je ne suis pas sûre d'avoir bien compris, mais une façon de faire est de faire un masque de bit, sur ceux qui t'intéresse, puis un décalage pour ramener tes bits sur le poids le plus faibles.

Voir le contraire :slight_smile: , un masque sur les 3 premiers bits et de décaler après pour le tour suivant.

1 Like

un octet c'est 8 bits, vous n'êtes donc pas garanti d'avoir un multiple de 3 quand vous lirez les bits (si la taille du message ne contient pas un nombre d'octets multiple de 3).

➜ où et comment doit se faire le padding du dernier groupe?

sinon avec ce schéma on voit assez bien qu'il n'est pas super compliqué d'écrire une fonction qui prend en paramètre le pointeur sur le message, le numéro du groupe à extraire et qui trouve le et les octets concernés et retourne les 3 bits associés

par exemple si vous avez N octets, le nombre de groupes c'est (N * 8) / 3 + 1 en division entière ➜ dans le dessin il y a 4 octets ==> 4 * 8 = 32, 32 / 3 = 10 en division entière et +1 ➜ on a 11 groupes numérotés de 0 à 10 donc

de même si on cherche le premier octet concerné pour un groupe N° G, alors comme il y a 3 bits par groupe, il se trouve à l'index (3 * G) / 8. Par exemple pour le groupe 2, le premier bit concerné est dans l'octet à l'index (3 * 2) / 8 = octet 0 ou de même pour le groupe 3, le premier bit concerné est dans l'octet à l'index (3 * 3) / 8 = octet 1

en jouant du modulo on peut aussi trouver si on est dans un seul octet ou s'il faut aller regarder le suivant

les 3 bits du groupe N° G sont donc aux index (3 * G), (3G+1) et (3G +2) bits du début de la séquence.

On a vu que l'octet contenant le bit à (3 * G) bits du début était (3 * G) / 8
➜ les bits étant numérotés depuis le poids fort 7 vers 0, le bit à extraire dans cet octet est donc 7 - ((G*3)%8)) dans l'octet N° (3 * G) / 8

idem pour les 2 autres bits et donc

soit N le nombre d'octets du message
On a (N * 8) / 3 + 1 groupes, numérotés de 0 à (N * 8) / 3

pour un groupe G dans cet intervalle

———————
le bit 0 est dans l'octet N° (3 * G) / 8 à la position binaire 7 - ((G*3)%8))
le bit 1 est dans l'octet N° (3 * G +1) / 8 à la position binaire 7 - ((G*3+1)%8))
le bit 2 est dans l'octet N° (3 * G + 2) / 8 à la position binaire 7 - ((G*3+2)%8))
il faut bien sûr que l'octet existe donc comparer l'octet calculé avec N sinon il faut du padding.
———————

Dans notre dessin où N = 4

par exemple pour le groupe G=5

  • le bit 0 est dans l'octet N° 1 à la position binaire 0
  • le bit 1 est dans l'octet N° 2 à la position binaire 7
  • le bit 2 est dans l'octet N° 2 à la position binaire 6

par exemple pour le groupe G=10

  • le bit 0 est dans l'octet N° 3 à la position binaire 1
  • le bit 1 est dans l'octet N° 3 à la position binaire 0
  • le bit 2 est dans l'octet N° 4 à la position binaire 7
    ==> on voit que pour le bit 2 l'octet N° 4 n'existe pas et donc il faudra faire un padding.

PS: au lieu de s'ennuyer avec du padding arbitraire qui sera difficile à décoder de l'autre côté, le plus simple est de s'assurer que le message contient un nombre multiple de 3 en octets en rajoutant un ou deux octets nuls ce qui fait que vous serez sûr de pouvoir découper le message en groupes de 3 bits.

1 Like

Oui ce serait possible de faire ça, mon professeur m'a dit qu'il faudrait ajouter un bit avant ou après lorsque le message n'est pas divisible par 3, mais le problème est que je ne sais pas comment écrire ce que je veux faire en code, j'ai mes idées, j'ai fais des recherches mais je ne trouve pas de moyen de le faire concrètement sur le programme...

j'ai rajouté un peu d'info dans le post précédent avec le dessin pour vous donner des idées sur les calculs à effectuer pour trouver les 3 bits

D'accord merci beaucoup, je vais bientôt aller a la fac, dès que j'arrive je regarde ça avec mon collègue.

Merci beaucoup pour toutes ces explications, elles me sont d'une grande aide, pour le moment nous n'allons pas faire de padding effectivement, car nous avons déjà le système permettant de décoder les messages.

Il nous faudra juste comme vous dite faire en sorte d'avoir un message divisible par 3. Cela étant dit, je suis vraiment un débutant en arduino et je ne connais vraiment pas les pointeurs, je ne sais pas par ou commencer pour attribuer une variable comme je le disais plus haut, pour chaque groupe de 3 bits, je ne sais pas du tout comment analyser toutes les valeurs de mon tableau binaire 3 par 3 et les comparer avec mes 8 conditions pour enfin dire quelle est leur variable (f0, f0+Δf, f0+2Δf etc..)

Est-ce que vous pourriez m'aider pour la rédaction du code ?

En tout cas, merci beaucoup de prendre de votre temps pour m'aider.

comme c'est un sujet scolaire, il faut que vous essayez. il n'y a pas vraiment besoin de pointeurs, vous pouvez utiliser la notation de tableaux et les fonctions sur les bits

  • pour aller chercher un octet à l'index i dans une chaîne pointée par texte, on utilise simplement texte[i]
  • pour aller chercher le bit b (entre 0 et 7) dans un octet o on utilise bitRead(o,b)
  • pour mettre le bit b (entre 0 et 7) à 1 dans un octet o on utilise bitSet(o,b)
  • pour mettre le bit b (entre 0 et 7) à 0 dans un octet o on utilise bitClear(o,b)

voici la structure de la fonction que vous pourriez utiliser pour fabriquer un octet dont les 3 bits de poids faible correspondent aux 3 bits extraits

byte get3Bits(const char * texte, size_t groupIndex, size_t nombreOctets) {
  byte les3bits = 0;  // par défaut on met des 0 partout
  size_t indexOctet;
  byte valeurDuBit;

  // pour aller chercher un octet à l'index i, on utilise simplement texte[i]
  // pour aller chercher le bit b (entre 0 et 7) dans un octet o on utilise bitRead(o,b)
  // pour mettre le bit b (entre 0 et 7) à 1 dans un octet o on utilise bitSet(o,b)
  // pour mettre le bit b (entre 0 et 7) à 0 dans un octet o on utilise bitClear(o,b)

  indexOctet = ....;                              // utiliser les formules
  if (indexOctet ...) {                           // tester si cet octet existe dans le texte
    valeurDuBit = ...;                            // utiliser les formules et bitRead
    if (valeurDuBit == 1) bitSet(les3bits, 2);    // si le premier bit doit être à 1, on le met
  }

  indexOctet = ....;                              // utiliser les formules
  if (indexOctet ...) {                           // tester si cet octet existe dans le texte
    valeurDuBit = ...;                            // utiliser les formules et bitRead
    if (valeurDuBit == 1) bitSet(les3bits, 1);    // si le deuxième bit doit être à 1, on le met
  }
  
  indexOctet = ....;                              // utiliser les formules
  if (indexOctet ...) {                           // tester si cet octet existe dans le texte
    valeurDuBit = ...;                            // utiliser les formules et bitRead
    if (valeurDuBit == 1) bitSet(les3bits, 0);    // si le troisième bit doit être à 1, on le met
  }

  return les3bits;
}

Avec mon collègue nous ne sommes pas sur d'avoir compris ce que vous voulez dire.

Ce que je comprends c'est que vous voulez que l'ont cherche les octets dans notre tableau, c'est à dire pour mon exemple AB : 0100000101000010 -> Dire que 01000001 est l'octet 1 et que 01000010 est l'octet 2 ?

Et que nous lisions ensuite le contenu de l'octet pour changer la valeurs des bits ?

Mais je ne comprends pas à quoi cela vas nous servir.
Je comprend que nous devons lire des bits dans nos octets, mais je ne comprends pas comment ce que vous venez de m'expliquer va me permettre d'attribuer une des 8 variables à mes paquets de 3 octets.

Je suis désolé je ne sais pas si c'est moi qui n'arrive pas a expliquer correctement ce que je veux ou si je suis juste dépassé par les explications...

Avant de passer au code, concentrez vous sur la spécification en français

➜ prenez un papier et un crayon. écrivez la suite binaire correspondant aux codes ASCII du message "SALUT" et faites tourner l'algorithme à la main pour voir si vous arrivez à bien remplir les 3 bits de poids faible de l'octet que vous voulez fabriquer

voici ce que vous devez savoir:

soit un message stocké dans un tableau de caractères appelé texte

soit N le nombre d'octets du message

on veut extraire par groupe de 3 bits le contenu du message.

on calcule simplement le nombre de groupes: (N * 8) / 3 + 1 (division entière)

Les groupes sont numérotés de 0 à (N * 8) / 3

pour un groupe N° G dans cet intervalle

  • le bit 2 est dans l'octet N° (3 * G) / 8 à la position binaire indexBit2 = 7 - ((G*3)%8))
  • le bit 1 est dans l'octet N° (3 * G +1) / 8 à la position binaire indexBit1 = 7 - ((G*3+1)%8))
  • le bit 0 est dans l'octet N° (3 * G + 2) / 8 à la position binaire indexBit0 = 7 - ((G*3+2)%8))

le symbole % est l'opérateur modulo (le reste lors de la division entière)
il faut bien sûr que les N° d'octets calculés existent donc comparer l'octet calculé avec N sinon il faut du padding.

Je comprend exactement ce que vous voulez qu'on fasse, sauf que nous ne devons pas créer d'octet pour stocker nos 3 bits, nous devons directement créer un tableau avec les valeurs que nous devons envoyer, voici un schéma de ce que j'aimerais faire.

pour remplir ce tableau vous aurez besoin de bâtir l'octet avec les 3 bits. ces 3 bits servant de multiplicateurs pour ∆f il vous suffit de stocker donc les octets obtenus par la fonction (en parcourant l'ensemble des groupes possibles) dans un tableau. à l'émission vous balancez f0 + octet x ∆f

il faut y aller petit à petit et séparer les problèmes

Ok je viens maintenant seulement de comprendre pourquoi nous devons les stocker dans des octets, les choses commencent à s'éclaircir, je me suis dit que j'avais compris, puis je suis retourné dans l'exemple de code que vous nous avez envoyé pour compléter, mais je ne sais toujours pas comment le compléter. Mon professeur de projet ayant 3 classes à gérer en même temps, il n'est pas en mesure de nous expliquer comment coder ce que l'on veut pour le moment.
Je fais en même temps mes recherches pour comprendre quoi faire en même temps mais pour un débutant je vous avoue que ça reste assez complexe.

faites vous la main sur des petits code d'exemple par exemple écrivez un code qui inverse les bits dans un octets

➜ jouez avec les fonctions arduino

Bits and Bytes

bit()
bitClear()
bitRead()
bitSet()
bitWrite()

écrivez un code qui affiche le nombre de groupes dans un texte

etc

Avant de faire du code, essaye comme te l'a indiqué @J-M-L de faire cela sur papier.
Essaye d'écrire un algorithme en Français, puis essaye de réécrire cette algorithme en intégrant du langage informatique(nom de fonction, affectation de variable, calcule sur les variables).
Cela te permettra d'identifier les points sur lesquels tu bloque et de faire des petits programme ne traitant que de ce problème.

Si on s'essaye avec ce que tu as donnée.

On peut faire un truc simplifié du genre.

Lire un octet du buffer à envoyer.
extraire les différents groupes de 3 bits pour les mettre dans une variables.
déduire les delta F à appliquer à la fréquence de référence en fonction des extractions.
passer à l'octet suivant.

si tu devais juste réécrire cette "algorithme" en étant plus proche d'un programme C que écrirais tu?

Si je devais faire ce que vous dites je ferais sans doute :

for (int i = 0; i < 8; i++)
byte = octet1 = bitRead(message, i)

Donc là j'aurais isolé le premier octet ?

Ensuite c'est là que je ne sais pas comment les trier par 3bits dans l'ordre

non ce n'est pas ça

faites le sur papier à la main.

J'essayerais avec mon collègue demain, merci de m'aider

allez y tres lentement

vous avez un tableau assez grand en variable globale pour contenir les "triplettes" de bits. Disons qu'on l'appelle triplettes

const byte nbMaxTriplettes = 100;
byte triplettes[nbMaxTriplettes]; // on peut stocker au max 100 triplettes

vous avez écrit une fonction get3Bits() qui extrait dans un octet une triplette identifiée par son N° de groupe dans un message texte.

la loop doit faire ceci

  • demander un message

  • calculer le nombre d'octets utilisés y compris l'octet nul de fin

  • si ce n'est pas un multiple de 3, rajouter des octets nuls en plus.

  • Se souvenir de ce nombre d'octets, ce sera nbOctets

  • calculer le nombre de groupes, ce sera nbGroupes

  • créer une boucle pour le groupe numéro g qui parcourt l'intervalle [0, nbGroupes[
    ** stocker dans triplettes[g] le résultat de get3Bits() pour le groupe N° g

➜ le tableau triplettes est maintenant initialisé avec nbGroupes valeurs

  • créer une boucle pour le groupe numéro g qui parcourt l'intervalle [0, nbGroupes[
    • envoyer la fréquence f0 + triplettes[g] * ∆t

ça bien sûr c'est la version un peu longue, car on peut se passer du tableau intermédiaire des triplettes puisqu'on peut le calculer à la volée lorsqu'on génère les fréquences

1 Like

Tu es passé directement au code, tu aurais pu essayer de faire un algorithme entre le code et le Français.

As tu essayé ton code ?