mardi 18 mai 2021

Portapack GNU Octave

Le Portapack permet d'enregistrer un signal radio capté par un HackRF One sur une carte micro-SD sans trimbaler un PC portable. En fait, j'ai un clone -H2 avec le logiciel Mayhem. Gnu Octave permet de traiter le signal sans trop d'effort (logiciel libre quasi compatible avec MATLAB). En fait, ici, je joue plus avec le signal que je le traite mais bon...
Pas sûr que le screenshot corresponde au signal traité ci-dessous, mais c'est l'idée. L'écran permet de repérer un signal qui semble intéressant, les boutons permettent la configuration de la réception et de lancer/stopper l'enregistrement sur la carte micro-SD.
En fait, le signal capté semble être quelque chose comme du dPMR (?). À mon souvenir, il était plus 'propre' et je ne suis même pas sûr que le filtre était indispensable.
$ dd if=BBD_0001.C16 of=_1.c16 bs=1M count=1
Histoire d'avoir un fichier de taille raisonnable (à 500ksamples/sec, cela fait 2MB/sec). On peut ensuite charger le fichier composé alternativement de I et de Q 16 bits signés dans un vecteur de nombres complexes en virgule flottante.
function y = loadC16File(filename)
%  y = loadC16File(filename)
%
% reads  complex samples from the portapack file 
%

fid = fopen(filename,'rb');
y = fread(fid,'int16=>double');

y = y(1:2:end) + i*y(2:2:end);
Ensuite, traiter le signal... Dans ce cas-ci, le filtre est trop large, la bande passante du signal est beaucoup plus étroite mais cela permet déjà d'y voir plus clair.
x0=loadC16File("_1.c16");
Ts=1/500000;
freqs=[0 0.2 0.21 1];
amps=[1 1 0 0];
b=remez(100, freqs, amps);
x=filter(b, 1, x0);
a=abs(x);
p=arg(x);
pp=unwrap(p);
fig=figure();
subplot(2,1,1);
plot(a);
title("abs(x) - magnitude");
subplot(2,1,2);
plot(pp);
title("unwrap(arg(x)) - argument/phase");
print(fig, "plot011.png", "-S800,800");
return; 
On prend une partie utile du signal (entre 5001 et 24500), on corrige légèrement la fréquence : ajout de 50 pi-radians sur 20000 échantillons pour redresser le graphe (je l'avais fait manuellement an ajoutant un linspace(), mais detrend() est fait pour cela) et on obtient :
ppp=pp(5001:24500);
pppdt = detrend(ppp,1);
fig=figure();
plot(pppdt);
axis([0 1 -50 50], "autox");
title("detrend(unwrap(arg(filter(x)))(5001:24500))");
print(fig, "coresigdt.png", "-dpng", "-S1280,360");
Tadaah... Il ne reste plus qu'à traduire ça en bits et bytes... (hum...; Ce n'est pas vraiment comme ça qu'il faut faire, mais bon...)