有段时间没研究NavTex了,这段时间打算捡起来继续搞。
上一篇文章中,我用frisnit生成了wav文件。然后再用gnuradio观察波形,发现波形确实能与frisnit中的描述以及python解码程序中的dictionary对应上。
接下来,我要重点想办法自己写代码实现自动解码。
我又仔细研究了一下python解码程序,目标是想办法把它转化为c++程序,然后再对接到gnuradio上,这样用gnuradio解调,用c++解码,就能基本实现navtex接收了。
我先看了看python程序,其实它是由两部分组成的。第一部分算音频fft频点+音频fsk(pll算法),实现了解调。解调出的每一时刻的频率值,就是每一时刻的采样点。第二部分,再针对这些采样点做解码,解出0101后,再解出字符。
我们的规划中,已经使用gnuradio实现了音频解调了。所以c++程序只要做第二部分。
我已经把上一篇文章的python代码的第二部分——解码部分已经都看懂了,确实能把gnuradio截图上显示的波形转换为正确的字符。并且符合下文描述
Free NAVTEX decoder / ナブテックスデコーダーフリーダウンロード (frisnit.com)
接下来要做的,就是想办法获得解调结果,把它和我们要写的c++程序连起来。
由于我们之前已经实现了从无线电的方式(portapack)发射wav,到无线电(hackrf)接收,直到解调出音频fsk对应的方波。为了简单起见,我们后续实验不再使用无线电收发来做实验,也不用声波收发来做实验。而是直接读取wav文件,得到方波,再把这种方波用类似nrf解码的方式,通过fifo送到后面的解码程序。
参考这篇文章
流图如下(建议wav file source的repeat改为no,用于精准调试):
后面我要重新下载NRF24-BTLE-Decoder,把它做简化,然后收fifo的输出,再print出来,把波形对应的每个采样点的值都打出来。一旦能打出来,离成功解码就不远了。
比如这样:
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#include <math.h>
#include <stdbool.h>
#include <inttypes.h>
int main (int argc, char**argv){
int16_t cursamp = 0;
int result = 0, last_result = 0;
int16_t counter = 0;
int real_counter = 0;
int buffer[10];
while(!feof(stdin) ) {
cursamp = (int16_t) ( fgetc(stdin) | fgetc(stdin)<<8);
counter++;
if (cursamp >= 0 )
{
result = 1;
}
else
{
result = 0;
}
if (last_result != result)
{
real_counter = (int)(counter / 440);
for (int i = 0; i < real_counter; i++)
{
buffer[i] = last_result;
}
for (int i = 0; i < real_counter; i++)
{
printf("%d", buffer[i]);
}
counter = 0;
last_result = result;
}
//printf("%d", result);
}
return 0;
}
上述代码配合gnuradio流图:
sudo rm /tmp/fifo
mkfifo /tmp/fifo
cat /tmp/fifo | ./nrf24-btle-decoder
111111000011001111110000110011111100001100111111000011001111110000110011111100001100111111000011001111110000110011111100001100111111000010110101100110101101111100010101010101101101010101011011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101101010110101011010101011001110101011111000101010101100111111000011001111110000110011111100001100111111000011
我们把它解码得到的二进制数字,截取一段,送到python程序中:
import numpy as np
import scipy
import scipy.signal
from scipy.io import wavfile
from navtex import ALPHABET_FIGS, ALPHABET_LTRS
#string = "1000111100011110001111000111100011110001111000111"
string = "1010101101010110101011010101101010110101011010101"
bits = list(string)
bits = np.array(bits)
N = 7
shift = 0
cur_alphabet_A = ALPHABET_LTRS
cur_alphabet_B = ALPHABET_LTRS
msg_a = ""
msg_b = ""
alpha_shift = 0
phased = False
phased_count = 0
i = 0
while i*N + shift < len(bits):
b = bits[i*N + shift:(i+1)*N + shift]
print (b)
s = "".join(map(str, b))
s = s[::-1]
h = int(s, 2)
if s.count('1') != 4:
phased_count -= 1
if phased_count < 10:
shift += 1
continue
else:
phased_count += 1
phased_count = min(50, phased_count)
# Regular symbols
if i % 2 == alpha_shift:
dec = cur_alphabet_A[h]
if dec == '[ltrs]':
cur_alphabet_A = ALPHABET_LTRS
elif dec == '[figs]':
cur_alphabet_A = ALPHABET_FIGS
elif not dec.startswith('['):
msg_a += dec
else:
dec = cur_alphabet_B[h]
if dec == '[ltrs]':
cur_alphabet_B = ALPHABET_LTRS
elif dec == '[figs]':
cur_alphabet_B = ALPHABET_FIGS
elif not dec.startswith('['):
msg_b += dec
i += 1
i = 0
print (msg_a)
以上代码要配合第B篇的navtex.py来用
运行后就会输出给你:
['1' '0' '1' '0' '1' '0' '1']
['1' '0' '1' '0' '1' '0' '1']
['1' '0' '1' '0' '1' '0' '1']
['1' '0' '1' '0' '1' '0' '1']
['1' '0' '1' '0' '1' '0' '1']
['1' '0' '1' '0' '1' '0' '1']
['1' '0' '1' '0' '1' '0' '1']
RRRR
这样一整套流程就做完了。
我们用gnuradio实现了解调,然后用c语言实现了初步的解码,再用python实现了最终的解码,得到了文字。
但我发现python解码的时候,如果截取的起始位搞错,结果是其他字符,所以还要优化。优化完后全部串起来,就可以实现整个接收机了。