波特率模拟

问题描述

我需要创建一个零调制解调器模拟来测试各种软件。我一直在使用 socat 来做到这一点:

socat -d -d pty,raw,echo=0 pty,echo=0 &

但我还需要模拟串口的基本波特率和各种长度的UART缓冲区的效果。 socat 的波特率 (b####)、ispeed 和 ospeed 参数在执行这种类型的 pty 环回时似乎没有任何影响。例如:

socat -d -d pty,echo=0,b50,ispeed=50,ospeed=50 pty,ospeed=50 &

应该会导致数据速率非常慢。然而,当通过此环回传递数据时,数据以最大机器速度传输。这并不令我感到惊讶,因为循环中没有真正的硬件。

那么,有没有一种方法可以在不编写自定义代码的情况下模拟 UART 时序?

我的最终目标是模拟像 Moxa 5600(16 个端口)这样的大型以太网到串行设备,以及串行吞吐量的影响如何影响 TCP 套接字流等...等等...

谢谢,

解决方法

我不认为这是一个实用的解决方案,但它很有趣。当您可以模拟真正的调制解调器时,为什么还要模拟一个空调制解调器。 minimodem 在某些发行版中作为包提供,可将数据转换为调制解调器音频音调,反之亦然。要尝试一下,只需以 10 波特率和 0.1 音量收听此音频:

$ echo 'the quick brown fox' | minimodem  -v 0.1 --tx 10

这大约需要 20 秒才能运行。如果你将输出定向到一个文件,它是即时的,但你可以用 sox“播放”文件并将音调解释回数据:

$ echo 'the quick brown fox' | minimodem  -v 0.1 --tx 10 -f out.wav 
$ file out.wav
  out.wav: RIFF (little-endian) data,WAVE audio,Microsoft PCM,16 bit,mono 48000 Hz
$ sox out.wav -t wav - | minimodem -f - --rx 10
  ### CARRIER 10.00 @ 1590.0 Hz ###
  the quick brown fox
  ### NOCARRIER ndata=20 confidence=33.775 ampl=0.064 bps=10.00 (rate perfect) ###

这仍然是即时的,但表明它有效。

要以合适的速度播放 wav 文件中的音调,需要通过音频设备播放。但是我们可以使用软件环回设备来做到这一点:

$ sudo modprobe snd-aloop
$ aplay -l
 **** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH],device 0: ALC662 rev1 Analog [ALC662 rev1 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH],device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: Loopback [Loopback],device 0: Loopback PCM [Loopback PCM]
  Subdevices: 7/8
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
  Subdevice #4: subdevice #4
  Subdevice #5: subdevice #5
  Subdevice #6: subdevice #6
  Subdevice #7: subdevice #7
card 1: Loopback [Loopback],device 1: Loopback PCM [Loopback PCM]
  Subdevices: 8/8
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
  Subdevice #4: subdevice #4
  Subdevice #5: subdevice #5
  Subdevice #6: subdevice #6
  Subdevice #7: subdevice #7

我们现在有 8 个环回设备(模块有一个参数要求更多)。例如,我们现在可以在卡 1、设备 1、子设备 2 上播放声音,并在卡 1、设备 0、子设备 2 上收听。 播放,需要 20 秒:

$ sox out.wav -t alsa hw:1,1,2 
out.wav:
 File Size: 1.96M     Bit Rate: 768k
  Encoding: Signed PCM    
  Channels: 1 @ 16-bit   
Samplerate: 48000Hz      
Replaygain: off         
  Duration: 00:00:20.40  
In:47.7% 00:00:09.73 [00:00:10.67] Out:467k  [    -=|=-    ]        Clip:0    

聆听:

$ sox -q -t alsa hw:1,2 -t wav -c 1 - | minimodem  --rx 10 -f -
### CARRIER 10.00 @ 1590.0 Hz ###
the quick brown fox
### NOCARRIER ndata=21 confidence=10.265 ampl=0.060 bps=10.00 (rate perfect) ###

字符需要 20 秒一个一个出现。

,

我记得 expect 有一个选项可以模拟人类打字,并且还可以为一些没有输入 fifo 并且非常挑剔的硬件设备慢慢地一个一个地输出字符。来自手册页(已编辑):

send_slow 采用两个元素的列表。第一个元素是 一个整数,描述要以原子方式发送的字节数。 第二个元素是一个实数,描述了 必须分开原子发送的秒数。例如, “set send_slow {10 .001}” 发送间隔 1 毫秒的字符串 每发送 10 个字符。

这是一个期望脚本 slowly,它使用该功能缓慢地将标准输入复制到标准输出。

#!/usr/bin/expect
# 8890 bd
set send_slow {1 .001}
# 17740
set send_slow {2 .001}
# 95970
set send_slow {10 .001}
# 143660
set send_slow {15 .001}
# 123210
set send_slow {14 .001}
# 107770
set send_slow {12 .001}

# time the run. get eg: 1866426 microseconds per iteration
set total 0
set runtime [time {
    while {1} {
     if {[eof stdin]} { break }
     set data [read stdin 99]
     send_user -s $data
     set total [expr $total + [string bytelength $data]]
    }
}]
set runtime [lindex $runtime 0]
set bps [expr $total * 1000 * 1000 / $runtime]
set baud [expr $bps * 10]
puts stderr "$runtime usecs $total bytes $bps bytes/sec $baud baud"

要尝试一下,请使文件可执行并为其提供一些数据,例如:

yes abcdefghijklmnopqrstuvwxyz | dd bs=27 count=1000 status=none >input
./slowly <input >output

通过上述,我得到了大约 107520 的波特率:

2510973 usecs 27000 bytes 10752 bytes/sec 107520 baud

通过将 send_slow 参数更改为 1 .001(并减小数据文件大小!),它可以降低到大约 9000 波特。为了变得更慢,1 .008 将达到大约 1230 波特。

send_human 类型的输出也可能有助于模拟某种类型的“抖动”类人数据流并清除一些错误。