Jari OH2ERJ toi eräseen kerhoiltaan mukanaan TETRA-kapulan ja ehdotti, että voisimme tallentaa pätkän sen lähetettä ja kokeilla, saadaanko sitä tulkittua mitenkään.
Etsimme gqrx-ohjelmalla ja rtl-sdr-vastaanottimella lähetteen, säädimme keskitaajuuden ja vahvistuksen sopivaksi ja tallensimme pätkän gqrx:llä. Näytteenottotaajuudeksi valittiin vain 300 kHz, ettei tiedostosta tulisi tarpeettoman suurta. Gqrx tallentaa nuo complex64-muodossa, jossa on peräkkäin näytteen reaaliosa (I) 32-bittisenä liukulukuna ja imaginääriosa (Q) samanlaisena. Tämä vie 4 kertaa enemmän tilaa kuin suoraan rtl_sdr-komentorivityökalulla tallennettu, mutta on toisaalta yleisemmin käytetty muoto. Tiedosto pakkautui kuitenkin aika hyvin ja tallenne löytyy bzip2-pakattuna täältä.
Avaamalla tallenne Audacityllä sen aikajakoisena lähetetyt purskeet näkyvät selvästi:
Seuraavassa kerhoillassa aloimme tutkia lähetettä tarkemmin. Latasimme osmo-tetra -ohjelman, joka ymmärtää jotain ainakin tukiasemien lähetteistä. (Lopussa on ohje, miten tämä ohjelma ladataan ja käännetään.)
Osmo-tetran mukana tuli skripti src/demod/cqpsk.py, joka demoduloi sopivassa muodossa olevan tallenteen, jotta se voidaan syöttää muille osmo-tetran osille. Skripti kuitenkin näytti haluavan eri näytteenottotaajuutta kuin mitä käytimme. Sieltä löytyi myös FUNcube donglen kanssa toimiva fcdp-tetra_demod.py. Halusimme muokata tuon toimimaan meidän tallenteille ja rtl-sdr-radioilla.
cqpsk.py-skriptiä lukemalla selvisi, että se oli suhteellisen yksinkertainen GNU Radiota käyttävä ohjelma, joka kytki muutaman GNU Radion peruslohkon peräkkäin sopivilla parametreilla. Ketju oli tällainen:
blocks.multiply_const_cc (Kertoo vakiolla: skaalaa signaalin halutulle lukuvälille)
-> analog.feedforward_agc_cc (Tason säätö: pitää signaalin keskimääräisen amplitudin sopivana)
-> filter.interp_fir_filter_ccf (Tekee TETRA-lähettessä käytetyn RRC-pulssinmuodon mukaisen suodatuksen)
-> digital.mpsk_receiver_cc (Synkronoi PSK-lähetteen eli säätää symbolikellon ja symbolien vaiheen oikeaksi)
-> digital.diff_phasor_cc (Kertoo näytteen edellisen näytteen konjugaatilla, jolloin saadaan vaiheen muutos kahden symbolin välillä. Tarvitaan, koska TETRA käyttää differentiaalista vaihemodulaatiota.)
-> blocks.complex_to_arg (Laskee kompleksiluvusta sen vaihekulman)
-> blocks.multiply_const_ff (Kertoo 4/piillä, jolloin vaiheesta -135° tulee -3, -45° -> -1, +45° -> +1 ja +135° -> +3. TETRAn PI/4 DQPSK tarkoittaa sitä, että vaiheen muutos symbolien välillä on tällä tavalla 45° eli PI/4 vinossa 90° moninkerrasta.)
Jotta kokeileminen olisi helpompaa, halusimme tehdä saman GNU Radio Companionilla (joka myös lopulta generoi samankaltaisen python-skriptin). Skriptiä lukemalla laitoimme samat palikat samoilla parametreilla onnistuneesti GNU Radio Companioniin ja aloimme muokata sitä hieman. Tällainen siitä tuli:
Linkki GRC-tiedostoihin ja Octave-skriptiin
Kokeilimme aluksi vastaanottaa jotain voimakkaasti kuuluvaa TETRA-tukiasemaa suoraan tallentamatta signaalia välissä. Syötimme nimetyn putken kautta symbolit osmo-tetran ohjelmille:
mkfifo /tmp/tetra
./float_to_bits /tmp/tetra /dev/stdout | ./tetra-rx /dev/stdin
Kumma kyllä, se lähti toimimaan, ja tetra-rx alkoi tulostaa tietoa löytämistään tukiaseman purskeista. Eihän se nyt näin helppoa voinut olla!
Mikään ennenkuulumaton saavutus tämä ei silti ole, koska telive-ohjelmisto tekee käsittääkseni saman. Koska teimme kuitenkin vähän enemmän itse, ymmärrämme paremmin mitä tässä tapahtuu. Selitetäänpä seuraavaksi, miten tämä ketju toimii.
Laitoimme MPSK-synkronoijan ottamaan sisään 4 näytettä per symboli. Koska TETRAn symbolinopeus on 18 kHz, täytyy blokille antaa signaalia näytteenottotaajuudella 4*18 kHz = 72 kHz.
Frequency Xlating FIR Filter ensin sekoittaa eli kertoo signaalin siniaallon kanssa, jolloin se siirtyy eri taajuudelle. Tässä se on säädetty niin, että tallenteessa olevan lähetteen keskitaajuus tulee 0 Hz kohdalle. (Huomaa, että kompleksisessa signaalissa näytteenottotaajuudella f on taajuuksia väliltä -f/2 ja +f/2). Sen jälkeen se tiputtaa näytteenottotaajuuden lähelle haluttua. Näytteenottotaajuuden muunnoksessa tarvitaan aliasoitumisen estämiseksi ja muutenkin signaalin suodattamiseksi alipäästösuodatin, jonka rajatajuudeksi laitettiin 20 kHz, jolloin se päästää kompleksisena 40 kHz kaistan.
Kun RTL-SDR:llä näytteistetään 1.8 MHz taajuudella, siitä päästään suoraan 25:llä jakamalla tuohon 72 kHz:n. Kapulan tallenteen olimme kuitenkin jo menneet tekemään 300 kHz taajuudella, josta tuohon ei päästä millään kokonaisluvulla jakamalla. Tämän vuoksi lisäsimme väliin Fractional Resampler -lohkon, joka osaa uudelleennäytteistää muillakin kuin kokonaislukusuhteilla:
Näin pääsimme kokeilemaan, mitä tetra-rx sanoo kapulan DMO-lähetteestä. Se näytti löytävän bittijonosta jotain, mutta ei saanut kuitenkaan ehjiä purskeita:
BURST
#### could not find successive burst training sequence
found SYNC training sequence in bit #4038
Tuli mieleen, että tuon MPSK Receiver -lohkon takaisinkytkentään perustuva symbolikellon synkronointi ei ehkä ehdi lukittua kunnolla kapulan lyhyeen purskeeseen. Tukiaseman kanssa se toimii kohtalaisesti, koska tukiasema lähettää lähes jatkuvasti. Kokeilimme ottaa synkronoinnin kokonaan pois ja laittaa RRC-suodattimeen desimoinnin siten, että se antaa yhden näytteen per symboli ulos. Ajatus oli, että silloin joillekin purskeille ajoitus osuisi riittävän lähelle oikeaa ja joillekin ei, mutta joku osa niistä saataisiin silti demoduloitua oikein. Samalla jäi pois saman lohkon tekemä kantoaallon vaiheen palautus, mutta sekin on oikeastaan tarpeeton, koska tarkastelemme vain vaiheen muutosta kahden peräkkäisen symbolin välillä. (Tälläinen differentiaalinen demodulointi huonontaa kyllä herkkyyttä hieman verrattuna koherenttiin, mutta tosiaan kestää taajuusvirhettä ja Doppler-leviämistä paremmin, koska varsinaista kantoaallon palautusta ei tarvita.)
Tämä ei oikeastaan muuttanut tulosta ja tetra-rx ei edelleenkään tulostanut mielestään ehjiä purskeita.
TETRAn speksiä lukemalla huomasimme, että tukiaseman downlinkin purske on hieman erimuotoinen kuin kapulan lähettämä uplink- tai DMO-purske.
( ETSI EN 300 392-2 sivu 82 )
Purskeiden keskellä on samanlainen bittijono (speksissä nimellä training sequence), jonka tetra-rx havaitsee, mutta ei löydä muita odottamiaan osia purskeesta, koska niitä ei kapulan lähetteessä ole.
Ajattelimme seuraavaksi kokeilla, löytyykö nuo tosiaan tuon float_to_bits-ohjelman antamasta bittijonosta laskemalla Octave-skriptillä vähän korrelaatioita.
../osmo-tetra/src/float_to_bits /tmp/tetra bitteja
octave
training
Huomasimme, että ”training sequence 1” tulee tasaisin välein, mutta silloin tällöin tulee myös ”training sequence 2”. Tämä ilmeisesti kertoo jotain purskeen sisällöstä ja tyypistä.
Kirjoitamme mahdollisesti myöhemmin lisää noista erimuotoisista purskeista, kunhan speksiä on selailtu lisää. Joissain pursketyypeissä on myös pidempiä sekvenssejä, joita ei vielä kokeiltu etsiä. Seuraavaksi voisi vaikka tehdä purskeille sopivan synkronoijan, joka etsii näytevirrasta näitä sekvenssejä ja sellaisen havaitessaan synkronoi näytekellon sekvenssiin ja antaa ulos suoraan yhden purskeen verran bittejä siitä ympäriltä.
Näköjään DMO:ssa nuo ovat lisäksi vähän erilaisia kuin uplinkissä:
ETR 300-3 sivu 68
ETS 300 396-2 sivu 42-43
Tässä vielä lyhyt ”ohje” osmo-tetran lataamiseen ja kääntämiseen Debian-, Ubuntu- tai Mint-Linux-distroilla:
sudo apt install build-essential libtool libtalloc-dev shtool autoconf automake git-core pkg-config make gcc libpcsclite-dev
mkdir ~/tetra
cd ~/tetra
git clone git://git.osmocom.org/libosmocore.git
git clone git://git.osmocom.org/osmo-tetra.git
mkdir ~/softa
export LIBRARY_PATH=~/softa/lib LD_LIBRARY_PATH=~/softa/lib C_INCLUDE_PATH=~/softa/include
cd ~/tetra/libosmocore
autoreconf -i
./configure --prefix=$HOME/softa
make -j4
make install
cd ~/tetra/osmo-tetra/src
make
Tämä ”ohje” kannattaa ottaa suuntaa-antavana esimerkkinä ja sitä voi soveltaa. Tässä tuo kirjasto asennetaan kotihakemiston alle, jolloin make installia ei tarvitse tehdä roottina. Jos päätit tehdä tämän ohjeen mukaan, muista antaa tuo export-komento myös jatkossa ennen osmo-tetran käyttöä. Ainiin, osmo-tetran Makefileen joutuu mahdollisesti lisäämään LDLIBS-muuttujan perään -ltalloc , jotta se kääntyy.
Jos et jaksa säätää GNU Radiota tai osmo-tetraa toimimaan, mutta haluat tarkastella bittejä, voit myös ladata samasta kapulan lähetteestä demoduloidun bittivirran. Huomaa, että tässä on purskeiden välissä satunnaisia bittejä eikä siitä suoraan näe, milloin purske alkaa ja loppuu.