Le code original du générateur PiFm a été amélioré par Richard Hirst pour tirer parti du DMA, de façon à réduire drastiquement la consommation de temps CPU : il s'agit de PiFmDma, dont je suis reparti. Restait à l'adapter pour la génération de signaux RDS. Je donne ici un résumé de l'approche suivie ; plus de détails peuvent être trouvés sur la page du projet Pi-FM-RDS.

Le RDS est un flux de données binaires à 1187,5 bit/s. Générer ce flux n'est pas bien difficile, il suffit de lire la norme pour générer les trames (groupes dans la terminologie RDS) correspondant aux services que l'on souhaite diffuser, et générer les mots de checksum. Ainsi je génère des groupes 0A (nom de la station) et 2A (radiotexte). Tout autre type de groupe peut s'ajouter très facilement. Chaque bit de ce flux doit ensuite donner lieu à deux impulsions, positive-négative ou bien négative-positive, dans un codage différentiel. Ce flux d'impulsions module en phase (BPSK) ou en amplitude, ce qui revient au même dans ce cas, une porteuse à 57 kHz qui est ajoutée au signal en bande de base de la station. En pratique l'amplitude du signal modulant varie continûment car le flux d'impulsions doit être filtré par un filtre RRC aussi bien au niveau de l'émetteur que du récepteur.

Mon approche consiste à travailler à 228 kHz, 4 fois la fréquence de la porteuse. J'ai pré-calculé la réponse du filtre RRC aux deux couples d'impulsions possibles, positive-négative et négative-positive. De la sorte, pour chacun des bits du flux de données à 1187,5 bit/s, j'ajoute à un buffer la réponse correspondante du filtre (ce que la norme appelle le symbole biphase). Je travaille à horizon de 3 bits, ce qui est suffisant pour générer un signal tout à fait correct. Cette façon de procéder me permet in fine d'appliquer le filtre RRC en faisant juste des additions, et pas la foule de multiplications qui résulteraient d'une application naïve du filtre (produit de convolution).

Le symbole biphase positif-négatif :

20140420_biphase_posneg.png

Succession de symboles biphase à raison de 1187,5 par seconde (NB : les symboles biphase se recouvrent partiellement et s'ajoutent...) :

20140420_unmodulated_signal.png

Il ne reste plus alors qu'à multiplier ce signal avec la porteuse à 57 kHz, ce qui est extrêmement simple à une fréquence d'échantillonnage de 228 kHz : la porteuse vaut successivement 0, +1, 0, -1, etc. Encore une fois, on échappe aux multiplications en bonne et due forme !

Au total, le programme qui génère et module les données RDS à la volée ne consomme que 9 % du temps CPU du Raspberry Pi.

Détail du signal précédent, une fois modulé sur la porteuse à 57 kHz :

20140420_modulated_signal.png

Réception obtenue sur une chaîne hifi :

20140420_vfd_display.jpg

J'ai ajouté la possibilité de jouer un signal audio, éventuellement stéréo, sur la modulation FM, à partir d'un fichier WAV de fréquence d'échantillonnage quelconque. Il faut donc sur-échantillonner ce signal en temps réel pour l'amener à 228 kHz. Pour cela, il faut appliquer un filtre passe bas, et là on n'échappe pas au produit de convolution... En FM stéréo, la consommation CPU grimpe à 40 %. La génération de la stéréo en elle-même ne pose pas de problème : il suffit de générer le « pilote stéréo », une porteuse sur 19 kHz (donc exactement 12 échantillons par alternance, qui sont pré-calculés) puis moduler en amplitude le signal « gauche moins droite » sur une porteuse à 38 kHz (donc exactement 6 échantillons par alternance, qui sont pré-calculés). On obtient finalement le spectre suivant :

20140420_spectre.png

J'ai donc présenté une technique complète de génération d'un signal RDS sur Raspberry Pi, qui tient largement le temps réel. La réception est parfaite sur tous les récepteurs que j'ai pu tester. À vous maintenant d'expérimenter et d'inventer de nouvelles applications au Raspberry Pi, mais je me dois de faire une mise en garde...

Attention, Pi-FM-RDS est un programme à caractère uniquement expérimental. Dans la plupart des pays, émettre des ondes radio sans autorisation est interdit. De plus, le générateur FM VHF génère un signal carré, donc riche en harmoniques, donc contraire à toute réglementation. Ne connectez donc jamais votre Raspberry Pi à une antenne. Si vous voulez tester, reliez-le directement à un récepteur par une ligne de transmission (câble coaxial par exemple), et, encore mieux, travaillez dans une cage de Faraday. Dans tous les cas, je ne pourrais être tenu responsable d'une utilisation illicite de mon programme.

Pour aller plus loin :

  • Le projet Pi-FM-RDS sur Github, diffusé sous licence GPL
  • Le site Framboise 314 a déjà publié un article sur Pi-FM-RDS.
  • Si vous souhaitez expérimenter avec le RDS, regardez le programme rds_wav : il utilise le moteur de génération de signal en bande de base de radio FM de Pi-FM-RDS, mais au lieu de piloter directement le Raspberry Pi, il enregistre le résultat dans un fichier WAV échantillonné à 228 kHz. Il est utilisable sur PC.
  • Discussion sur Reddit
  • Norme RDS de 1998