jeudi 21 juillet 2016

AIS toujours

Évolution de la phase lors d'un message AIS (le 'Curata' de passage à Liège le 19 juillet 2016)
$ rtl_sdr -f 162025000 -s 249600 f.iq
$ rtl_dump -p < f.iq > phase
La phase est obtenue avec rtl_dump. L'allure générale est due à un décalage entre la fréquence d'émission et la fréquence de réception. On a, environ, 5700° sur 5994 échantillons, ce qui correspond à 660 Hz ((5700/360)*(249600/5994)); --à vérifier--

En fait, il faudrait s'intéresser à la stabilité de la fréquence de réception (et sa variation de clé en clé).

$ rtl_sdr -f 162024400 -s 249600 f.iq
rtl_fftmax permet de voir s'il y a quelque chose dans le fichier :
$ /rtl_fftmax -f 162024400 -s 249600 -n 1024 core
On voit que le fichier contient des messages des deux canaux AIS, en 161.975 MHz et 162.025 MHz.

Dans un autre enregistrement d'environ 88 secondes à la Citadelle de Liège centré sur 162.025 MHz, si on applique l'algorithme de Goertzel avec N=512 sur les 'I', on obtient :
Le canal 'A' est obtenu en cherchant la présence de -50 kHz; 'B' à 0 KHz. En regardant de près dans Gnuplot, on peut facilement repérer où sont les messages dans le fichier binaire 'iq'.

Si je ne prends que les IQ des blocs où le test de Goertzel à 25 kHz est positif dans un enregistrement d'une minute centré sur 162 MHz et que je trace la phase en veillant à ce qu'elle soit continue, j'obtiens le graphe :
Ce qui est très encourageant. Les zones montantes concernent le +25 kHz, celles descendantes, le -25 kHz. On a aussi, probablement des collisions entre les deux fréquences qu'il faudrait départager avec un filtre. À noter qu'une translation en fréquence peut se traduire par la multiplication par un sinus. Le IQ étant des e^jwt, si on les multiplie par des e^jdwt, on obtient des e^(j(w+dw)t)... Et donc, l'idée de 'corriger la pente' en ajoutant simplement des a*t à la phase ne semble pas complètement farfelue (bien que probablement un peut trop intuitive (?)).

Notons que le graphe, sur une minute, comprends plus de 200000 points et qu'à 26 points par bits, on arrive à environ 40 messages de 200 bits. Ce qui, si on parvient à les décoder sans erreur, ne serait pas mal du tout.

Voir aussi

lundi 27 juin 2016

Balise CC1101

Observer passivement les ondes avec une clé TNT (RTL-SDR), c'est bien mais ce serait bien aussi d'avoir une référence paramétrable disponible à tout moment. Une possibilité est d'utiliser ces modules pour Arduino avec un CC1101 de Texas Instruments, que l'on trouve à quelques euros sur eBay. Ils sont conçus pour émettre (et recevoir) dans la bande ISM 433 MHz. Plusieurs types de modulations FSK sont programmables, ainsi divers paramètres comme la puissance d'émission, le baud rate, la variation de fréquence,... Ainsi que différents formats et encodages de trame. La datasheet ne fait pas loin de 100 pages et il existe de nombreuses 'application notes' sur divers aspects de la mise en œuvre. On peut, par exemple, s'en servir pour comparer des antennes. Une autre application, c'est d'observer de près des signaux plus ou moins connus. Par exemple, à partir de la configuration utilisée par la librairie panstamp (générée par l'utilitaire de Texas Instrument 'SmartRF Studio'),
uint8_t panstamp_config[] =
        {
/*00*/  0x2E, 0x2E, 0x06, 0x07, 0xB5, 0x47, 0x3D, 0x06,
        0x05, 0xFF, 0x00, 0x08, 0x00, 0x10, 0xA7, 0x62,
/*10*/  0xCA, 0x83, 0x93, 0x22, 0xF8, 0x35, 0x07, 0x20, /* datarate (CA) = 38.4 kbauds*/
        0x18, 0x16, 0x6C, 0x43, 0x40, 0x91, 0x87, 0x6B,
/*20*/  0xFB, 0x56, 0x10, 0xE9, 0x2A, 0x00, 0x1F, 0x41,
        0x00, 0x59, 0x7F, 0x3F, 0x81, 0x35, 0x09
        };

/*10    0xC7, 0x83, 0x83, 0x22, 0xF8, 0x35, 0x07, 0x20, /* data_rate (C7) = 4800 bauds; 2FSK(83)*/
où R[0x10], MDMCFG4, est 0xCA (et R[0x11], MDMCFG3 = 0x83) qui correspond à 38383 symboles par seconde et R[0x12] est 0x93 (GFSK). Si on remplace ces valeurs par, respectivement, 0xC7 (4800 bauds) et 0x83 (2-FSK), on obtient un signal plus facile à observer/analyser avec une clé RTL-SDR. En zoomant sur la phase (arc tangente(I/Q); ou, serait-ce Q/I?) du signal reçu lors du préambule, on observe :
On observe que la phase décroît jusque A, croît entre A et B, décroît entre B et C pour ensuite recroître (les transitions autour de 0/360 provoquent un saut dont il ne faut pas tenir compte). La phase croît lorsque la fréquence est supérieure à la référence et décroît lorsque la fréquence est inférieure. En regardant de plus près, on note les coordonnées des points : A=(12585,130) B=(12634,150) et C=(12682,8). On compte donc 48 (ou 49) échantillons entre les points. Et, 230000 (échantillons/seconde) divisé par 48, cela donne bien 4792 symboles par seconde (~4800 bauds). En observant le gain (ou la perte) de phase entre deux points, on devrait retrouver l'écart de fréquence programmé pour le 2-FSK. A->B, +1460°; B->C, -1582°. L'asymétrie provient d'une erreur dans l'estimation de la fréquence de référence (ou, plus exactement, de quartz approximatifs; la fréquence choisie étant 433 MHz des deux côtés. Coupons la poire en deux et estimons que la phase progresse de 1500° 4800 fois par seconde, c'est-à-dire, 7200000° ou 20000 'tours', c.-à-d., 20 kHz. Et c'est exactement ce que l'on retrouve dans R[0x15], DEVIATN = 0x35. Une telle déviation est probablement excessive pour 4800 bauds; c'était prévu pour 38400 bauds. C'est aussi ce que l'on observe avec GNU Radio :
Le profil serait probablement plus doux en GFSK; en évitant les changements abrupts de fréquences. À noter que ces affichages FFT et Waterfall sont, un peu, des gadgets : un court message (du genre 8 caractères avant l'ajout du préambule et le CRC) est envoyé environ 7 fois par seconde (duty-cycle ~.25) et il ne s'affiche pas à chaque fois. J'ignore quelle est la proportion de signal non traité mais la traque aux messages courts et rares est un peu aléatoire avec ce genre d'outil. Si je mets 0x00 dans DEVIATN, j'obtiens la déviation minimale, 1587 Hz. À noter que c'est trop grand pour émuler un modem Bell 202. Par exemple, pour simuler un APRS venant d'ISS.
Si on regarde une trame complète en rapprochant la fréquence de réception de la fréquence d'émission (433 001 210 Hz plutôt que 433 000 000) et qu'on évite les sauts du côté de 0-360, cela donne le graphe :
On voit que la fréquence peut rester la même pendant un grand nombre de symboles (par exemple, quand on transmet des 0x00). Une possibilité est d'utiliser la fonction 'whitening' du chip qui fait un XOR avec un nombre pseudo-aléatoire. Une autre est d'utiliser un codage Manchester en mettant le bit 0x08 de R[0x12], MDMCFG2, à 1. On obtient alors le graphe :
...qui ressemble étrangement à celui de la grue du billet précédent. Sauf que dans le cas de la grue, les changement de fréquences sont 'arrondis', il doit s'agir de GFSK (?). On notera également que le codage Manchester engendre une diminution du débit utile.

La clé TNT utilisée ici est la petite : RT2832U avec un tuner R820T :


À suivre...

samedi 9 avril 2016

RTL-SDR SigInt

Lors du FOSDEM 2016, Felix Wunsch a présenté le SigInt comme une activité ludique et enrichissante... Équipé d'un de ces gadgets à moins de 10 euros sur eBay, une clé TNT avec un chip Realtek RTL2832U, je m'en vais faire un tour avec le LiveDVD GNU Radio sur la bande ISM 433 MHz :
Tiens!, il y a un joli signal assez puissant et bien stable... En fait, ce n'est pas tout le temps mais quand le signal est présent, il reste stable longtemps. Tout porte à croire qu'il s'agit de la télécommande de la grue du chantier en face... (les horaires et l'activité coïncident avec la présence du signal)
Comme on peut le voir sur l'affichage I/Q de la copie d'écran GNU Radio, ce n'est pas une modulation d'amplitude, la trace est un cercle (d'amplitude constante). En y regardant de plus près, en utilisant la commande
$ rtl_sdr -f 433630000 -s 256000 file
et d'un petit programme 'rtl_dump -p' pour sortir la phase en texte, on obtient avec Gnuplot quelque chose comme :
Le gain automatique (AGC) fait varier la puissance du signal qui sature un peu à l'extérieur mais bon. Ce qui est amusant, c'est que la phase semble 'tourner' (à magnitude constante). En fait, c'est dû au fait que la fréquence de réception choisie ne correspond pas exactement à la fréquence d'émission (en charabia : 'frequency offset' -> 'spinning constellation' en démodulation QAM). J'ai estimé la fréquence en regardant le 'waterfall'; ce n'est pas assez précis. Il existe des techniques pour retrouver la fréquence correcte mais on verra ça plus tard... Pour le moment, c'est bon assez pour voir si on peut en tirer quelque chose. Si l'on s'intéresse à l'évolution de la phase, on obtient bien quelque chose de structuré :
En zoomant,
on voit que le signal est très propre mais que les sauts autour de 0-360° rendent l'interprétation difficile. En assurant la continuité et en laissant croître la phase au delà de 360°, cela devient plus clair :
Cette dérive vers le haut est un peu gênante, on peut la supprimer artificiellement en soustrayant la pente (-i*alpha):
Et voilà une jolie trame bien propre (mais un peu asymétrique) qu'il ne reste plus qu'à analyser...

Si j'écris un petit programme qui mesure les montées et les descentes des données (montantes), j'obtiens quatre nuages de points bien séparés représentant les montées/descentes courtes/longues :
On notera également que l'on n'a pas n'importe quelle suite de transitions. On n'a pas de suite {courte descente+longue montée} ni de suite {courte montée+longue descente}. En fait, si on considère 4 positions de hauts et bas de courbe, on peut avoir les transitions 1->{2|4}, 2->1, 3->4 et 4->{3|1}. Seuls les départs de 1 et 4 permettent de coder 1 bits. Une petite transition est d'office suivie d'une petite transition qui ramène l'état à son point de départ. Une difficulté de ce petit programme est de commencer et finir aux bons endroits et éviter les parasites.

On peut déjà regarder si les trames se ressemblent en les mettant côte à côte :


Normalement, il faudrait filtrer pour purifier le signal, utiliser la fréquence correcte et ensuite synchroniser et corréler pour extraire les bits. Mais le signal est propre et semble facile à décoder avec un petit programme ad hoc. Mettons qu'on imprime '1' pour deux 'petites' transitions successives et '0' pour une grande transition. Les dix premières trames donnent :
111111000000000000000000010111010010000000011011011101100010101010101100000010010000000010000000010000000010000000010000000010000000010000111010001111100001011101110100010000000001111
0011000000000000000000010111010010000000011011011101100010101010110010000010010000000010000000010000000010000000010000000010000000011001001010001000100001011101110100010000000001111
111110001000000000000000000010111010010000000011011011101100010101010110100000010010000000010000000010000000010000000010000000010000000010001001101010111010001011101110100010000000001111
1110001000000000000000000010111010010000000011011011101100010101010111010000010010000000010000000010000000010000000010000000010000000011001100100111111010001011101110100010000000001111
111111011000000000000000000010111010010000000011011011101100010101010111100000010010000000010000000010000000010000000010000000010000000010001100011100000100001011101110100010000000001111
1111111011000000000000000000010111010010000000011011011101100010101010000010000010010000000010000000010000000010000000010000000010000000011010100100111001100001011101110100010000000001111
11111101011000000000000000000010111010010000000011011011101100010101010000100000010010000000010000000010000000010000000010000000010000000010010100011100110010001011101110100010000000001111
11111111110001000000000000000000010111010010000000011011011101100010101010001010000010010000000010000000010000000010000000010000000010000000011010001010001110010001011101110100010000000001111
01000000000000000000010111010010000000011011011101100010101010001100000010010000000010000000010000000010000000010000000010000000010010001101010001100001011101110100010000000001111
011000000000000000000010111010010000000011011011101100010101010010010000010010000000010000000010000000010000000010000000010000000011011111101010110100001011101110100010000000001111
C'est amusant, des similarités apparaissent mais, pour une raison inconnue, elles ne sont pas alignées. Si on les aligne, cela donne :
000000000000000000010111010010000000011011011101100010101010101100000010010000000010000000010000000010000000010000000010000000010000111010001111100001011101110100010000000001111
000000000000000000010111010010000000011011011101100010101010110010000010010000000010000000010000000010000000010000000010000000011001001010001000100001011101110100010000000001111
000000000000000000010111010010000000011011011101100010101010110100000010010000000010000000010000000010000000010000000010000000010001001101010111010001011101110100010000000001111
000000000000000000010111010010000000011011011101100010101010111010000010010000000010000000010000000010000000010000000010000000011001100100111111010001011101110100010000000001111
000000000000000000010111010010000000011011011101100010101010111100000010010000000010000000010000000010000000010000000010000000010001100011100000100001011101110100010000000001111
000000000000000000010111010010000000011011011101100010101010000010000010010000000010000000010000000010000000010000000010000000011010100100111001100001011101110100010000000001111
000000000000000000010111010010000000011011011101100010101010000100000010010000000010000000010000000010000000010000000010000000010010100011100110010001011101110100010000000001111
000000000000000000010111010010000000011011011101100010101010001010000010010000000010000000010000000010000000010000000010000000011010001010001110010001011101110100010000000001111
000000000000000000010111010010000000011011011101100010101010001100000010010000000010000000010000000010000000010000000010000000010010001101010001100001011101110100010000000001111
000000000000000000010111010010000000011011011101100010101010010010000010010000000010000000010000000010000000010000000010000000011011111101010110100001011101110100010000000001111
En hexadécimal, cela pourrait donner quelque chose comme (dc; 16o2i ...p; 'pourrait' parce qu'il faut encore aligner et voir si c'est le LSB ou le MSB qui est transmit en premier) :
02E900DBB155604804020100804021D1F0BBA200F
02E900DBB1559048040201008040325110BBA200F
02E900DBB155A048040201008040226AE8BBA200F
02E900DBB155D0480402010080403327E8BBA200F
02E900DBB155E048040201008040231C10BBA200F
02E900DBB1541048040201008040352730BBA200F
02E900DBB1542048040201008040251CC8BBA200F
02E900DBB15450480402010080403451C8BBA200F
02E900DBB1546048040201008040246A30BBA200F
02E900DBB154904804020100804037EAD0BBA200F
On trouve des choses constantes et d'autres qui ne le sont pas. Probablement qu'en analysant un grand nombre de trames dans un grand nombres de circonstances on parviendrait à décoder tout cela. Et, en comparant différentes grues, y découvrir une adresse, un modèle,... (?)

Les tests du billet suivant laissent à penser qu'il pourrait s'agir d'un encodage Manchester en GFSK à 9600 bauds (?; le CC1101 ne semble pas pouvoir du Manchester en MSK (qui 'arrondit' mieux l'évolution de la phase)).

(à suivre?)