Portapack应用开发教程(十五) APRS接收

APRS功能可以用对讲机来传输数字信息,以便在没有运营商网络的环境下共享位置,实现类似微信的位置共享功能,也可以用它来发短消息。

有人买直接带aprs的对讲机,比较贵。也有人用普通对讲机和手机通过音频线对接,然后手机上运行aprsdroid软件来实现同样的功能。

 

它的原理跟sstv比较类似,都是两次fm,把数据进行编码(手机中完成),然后用音频的高低音来表示编码10101(手机中完成),再把这个编码再次做fm调制(对讲机中实现)最终发射出去。

portapack可以把手机和对讲机合并在一起,还是利用sstv中类似的方法就能完成。

furrtek固件里已经有一个aprs tx软件,虽然是黄色图标(代表不完善),但是根据一位朋友的反馈,已经可以用它发射信号,然后用对讲机+aprsdroid来成功解码。

现在我来做一个aprs rx就行。

 

我打算先用一个portapack的aprs tx来发射,然后用hackrf+电脑来做fm解调代替对讲机,然后用aprsdroid来解码体验一下。

然后把aprsdroid解码部分用c++实现,再往portapack移植就行了。

 

但是我发现aprsdroid程序虽然开源,但是用scala语法写的,我还不太熟悉。

所以我就直接看了portapack里的各种代码,我发现portapack中的aprs tx程序只是做了上层编码,它的底层是afsk tx。

发射部分调用关系如下:

ui_aprs_tx.cpp (make_aprs_frame) -> aprs.cpp (make_ui_frame) -> ax25.cpp (shared_memory.bb_data.data) -> proc_afsk.cpp (word_ptr)

而portapack的接收部分里已经有了一个afsk rx了,用它来解调,只要做好上层解码就行了。

我仔细看了一下proc_afsk.cpp(发射调制)和proc_afskrx.cpp(接收调制)。

proc_afsk.cpp(execute函数)

		if (cur_bit)
			tone_phase += afsk_phase_inc_mark;
		else
			tone_phase += afsk_phase_inc_space;

		tone_sample = sine_table_i8[(tone_phase & 0xFF000000U) >> 24];

		delta = tone_sample * fm_delta;
		
		phase += delta;
		sphase = phase + (64 << 24);

		re = (sine_table_i8[(sphase & 0xFF000000U) >> 24]);
		im = (sine_table_i8[(phase & 0xFF000000U) >> 24]);
			
		buffer.p[i] = {re, im};

 这部分代码跟sstv发射的对应部分差不多,通过操作tone_phase,就能发射两次fm的信号,只不过sstv里影响tone_phase的是像素点的颜色值,而这里是mark和space。我觉得它们就对应1和0。

 porc_afskrx.cpp (execute函数)

一开始在做第一次的fm解调,从无线电信号变为音频信号,相当于是一个对讲机。

得到音频信号后要再做一次fm解调。下方代码就在做这个事,跟我sstv接收里的音频fm解调效果差不多的,早知道我就直接参考它这里代码了。

原理就是sdrsharp讲解里也讲过的,把信号作延迟再乘以本身的信号就行,这个delay line在rtlsdr的那本书里也讲过。

// Delay line put
		delay_line[delay_line_index & 0x3F] = current_sample;
		
		// Delay line get, and LPF
		sample_mixed = (delay_line[(delay_line_index - (samples_per_bit/2)) & 0x3F] * current_sample) / 4;
		sample_filtered = prev_mixed + sample_mixed + (prev_filtered / 2);
		
		delay_line_index++;
		
		prev_filtered = sample_filtered;
		prev_mixed = sample_mixed;
		
		// Slice
		sample_bits <<= 1;
		sample_bits |= (sample_filtered < -20) ? 1 : 0;
		
		// Check for "clean" transition: either 0011 or 1100
		if ((((sample_bits >> 2) ^ sample_bits) & 3) == 3) {
			// Adjust phase
			if (phase < 0x8000)
				phase += 0x800;		// Is this a proper value ?
			else
				phase -= 0x800;
		}
		
		phase += phase_inc;

sample_filtered里面是解调出来的音频频率,照道理这里要根据设置的mark和space频率值来灵活配置,不知道为啥只是以-20作为阈值来判断当前采样对应1或0。

下面这段根据不同的协议来把sample_bits转为word_bits然后传送给程序的其他部分。

if (trigger_word) {
				
				// Continuous-stream value-triggered mode (AX.25) - UNTESTED
				word_bits <<= 1;
				word_bits |= (sample_bits & 1);
				
				bit_counter++;
				
				if (triggered) {
					if (bit_counter == word_length) {
						bit_counter = 0;
						
						data_message.is_data = true;
						data_message.value = word_bits & word_mask;
						shared_memory.application_queue.push(data_message);
					}
				} else {
					if ((word_bits & word_mask) == trigger_value) {
						triggered = !triggered;
						bit_counter = 0;
						
						data_message.is_data = true;
						data_message.value = trigger_value;
						shared_memory.application_queue.push(data_message);
					}
				}
				
			} else {
				
			
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值