radio 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +202 -0
- data/README.md +67 -1
- data/bin/radio-server +8 -0
- data/lib/radio.rb +41 -1
- data/lib/radio/controls/null.rb +32 -0
- data/lib/radio/controls/si570avr.rb +77 -0
- data/lib/radio/filter.rb +69 -0
- data/lib/radio/filters/fir.rb +65 -0
- data/lib/radio/gif.rb +84 -0
- data/lib/radio/http/file.rb +88 -0
- data/lib/radio/http/script.rb +133 -0
- data/lib/radio/http/server.rb +94 -0
- data/lib/radio/http/session.rb +43 -0
- data/lib/radio/input.rb +62 -0
- data/lib/radio/inputs/alsa.rb +135 -0
- data/lib/radio/inputs/coreaudio.rb +102 -0
- data/lib/radio/inputs/file.rb +60 -0
- data/lib/radio/inputs/wav.rb +124 -0
- data/lib/radio/psk31/bit_detect.rb +19 -4
- data/lib/radio/psk31/decoder.rb +18 -3
- data/lib/radio/psk31/fir_coef.rb +6 -1
- data/lib/radio/psk31/rx.rb +27 -32
- data/lib/radio/psk31/varicode.rb +15 -0
- data/lib/radio/rig.rb +46 -0
- data/lib/radio/rig/lo.rb +57 -0
- data/lib/radio/rig/rx.rb +61 -0
- data/lib/radio/rig/spectrum.rb +96 -0
- data/lib/radio/version.rb +3 -0
- data/test/test.rb +76 -0
- data/test/wav/bpsk8k.wav +0 -0
- data/test/wav/qpsk8k.wav +0 -0
- data/test/wav/ssb.wav +0 -0
- data/www/index.erb +40 -0
- data/www/jquery-1.7.js +9300 -0
- data/www/lo.erb +21 -0
- data/www/setup/input.erb +64 -0
- data/www/setup/lo.erb +36 -0
- data/www/waterfall.erb +20 -0
- metadata +77 -9
- data/lib/radio/psk31/filters.rb +0 -220
data/www/lo.erb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
<% if xhr?
|
2
|
+
$rig.lo = params['freq'].to_f
|
3
|
+
@response.body = [$rig.lo.to_s]
|
4
|
+
@response.headers['Content-Type'] = 'text/plain'
|
5
|
+
end -%>
|
6
|
+
<form action="lo" id="freqForm">
|
7
|
+
<input type="text" name="freq" value="<%= $rig.lo %>" %>
|
8
|
+
</form>
|
9
|
+
<script type="text/javascript">
|
10
|
+
$("#freqForm").submit(function(event) {
|
11
|
+
event.preventDefault();
|
12
|
+
var $form = $( this ),
|
13
|
+
term = $form.find( 'input[name="freq"]' ).val(),
|
14
|
+
url = $form.attr( 'action' );
|
15
|
+
$.post( url, { freq: term },
|
16
|
+
function( data ) {
|
17
|
+
$form.find( 'input[name="freq"]' ).val(data)
|
18
|
+
}
|
19
|
+
);
|
20
|
+
});
|
21
|
+
</script>
|
data/www/setup/input.erb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
<%
|
2
|
+
if post?
|
3
|
+
$rig ||= Radio::Rig.new
|
4
|
+
channel_i, channel_q = case params['channel']
|
5
|
+
when 'iq' then [0,1]
|
6
|
+
when 'qi' then [1,0]
|
7
|
+
else [0,nil]
|
8
|
+
end
|
9
|
+
$rig.rx = Radio::Input.new params['type'], params['id'], params['rate'].to_i, channel_i, channel_q
|
10
|
+
response.redirect '/'
|
11
|
+
end
|
12
|
+
unless response.redirection? -%>
|
13
|
+
<!DOCTYPE html>
|
14
|
+
<html>
|
15
|
+
<head>
|
16
|
+
<style type="text/css" media="screen">
|
17
|
+
body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}
|
18
|
+
select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}
|
19
|
+
</style>
|
20
|
+
</head>
|
21
|
+
<body>
|
22
|
+
|
23
|
+
<h2>Input Sources</h2>
|
24
|
+
<% if (input_sources = Radio::Input.sources).empty? -%>
|
25
|
+
No input sources found.
|
26
|
+
<% else -%>
|
27
|
+
<dl>
|
28
|
+
<% input_sources.each do |k, opts| -%>
|
29
|
+
<form action='?' method="post">
|
30
|
+
<% input_type, input_id = k -%>
|
31
|
+
<dt>
|
32
|
+
<input type="submit" value="Select"%>
|
33
|
+
<input type="hidden" name="type" value="<%=h input_type %>" %>
|
34
|
+
<input type="hidden" name="id" value="<%=h input_id %>" %>
|
35
|
+
<%=h input_type %>: <%=h opts[:name] %>
|
36
|
+
</dt>
|
37
|
+
<dd>
|
38
|
+
<% opts[:rates].reverse.each_with_index do |rate, index| %>
|
39
|
+
<input type="radio" name="rate" value="<%=h rate %>" <%= "checked=checked" if index==0 %> /><%=h rate %>
|
40
|
+
<% end -%>
|
41
|
+
</dd>
|
42
|
+
<dd>
|
43
|
+
<% if opts[:channels] == 1 or input_type != :File %>
|
44
|
+
<input type="radio" name="channel" value="i" checked="checked" />LPCM
|
45
|
+
<% end -%>
|
46
|
+
<% if opts[:channels] == 2 %>
|
47
|
+
<input type="radio" name="channel" value="iq" />I/Q
|
48
|
+
<input type="radio" name="channel" value="qi" checked="checked" />Q/I
|
49
|
+
<% end -%>
|
50
|
+
</dd>
|
51
|
+
</form>
|
52
|
+
<br />
|
53
|
+
<% end -%>
|
54
|
+
</dl>
|
55
|
+
<% end -%>
|
56
|
+
|
57
|
+
<h2>Driver Status</h2>
|
58
|
+
<% Radio::Input.status.each do |k, v| -%>
|
59
|
+
<%=h k %>: <%=h v %> <br />
|
60
|
+
<% end -%>
|
61
|
+
|
62
|
+
</body>
|
63
|
+
</html>
|
64
|
+
<% end -%>
|
data/www/setup/lo.erb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
<%
|
2
|
+
if post?
|
3
|
+
$rig.lo = case params['type']
|
4
|
+
when 'softrock' then Radio::Controls::Si570AVR.new
|
5
|
+
else Radio::Controls::Null.new
|
6
|
+
end
|
7
|
+
response.redirect '/'
|
8
|
+
end
|
9
|
+
unless response.redirection? -%>
|
10
|
+
<!DOCTYPE html>
|
11
|
+
<html>
|
12
|
+
<head>
|
13
|
+
<style type="text/css" media="screen">
|
14
|
+
body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}
|
15
|
+
select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}
|
16
|
+
</style>
|
17
|
+
</head>
|
18
|
+
<body>
|
19
|
+
|
20
|
+
<h2>Local Oscillator Control</h2>
|
21
|
+
<form action='?' method="post">
|
22
|
+
<input type="submit" value="Select"%>
|
23
|
+
<input type="hidden" name="type" value="null" %>
|
24
|
+
No control.
|
25
|
+
</form>
|
26
|
+
<br />
|
27
|
+
<form action='?' method="post">
|
28
|
+
<input type="submit" value="Select"%>
|
29
|
+
<input type="hidden" name="type" value="softrock" %>
|
30
|
+
SoftRock Si570 (DG8SAQ/PE0FKO)
|
31
|
+
</form>
|
32
|
+
<br />
|
33
|
+
|
34
|
+
</body>
|
35
|
+
</html>
|
36
|
+
<% end -%>
|
data/www/waterfall.erb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
<%
|
2
|
+
$waterfall_gradient ||= (0..127).collect do |i|
|
3
|
+
r = g = b = Math.log((i+16)**6.35)*18-312
|
4
|
+
redshift = i - 64
|
5
|
+
if redshift > 0
|
6
|
+
b = g -= redshift * 3
|
7
|
+
end
|
8
|
+
b *= 0.95
|
9
|
+
[r,g,b]
|
10
|
+
end
|
11
|
+
spectrum = case
|
12
|
+
when $rig.rate <= 24000 then $rig.spectrum 1024, 1.0
|
13
|
+
when $rig.rate <= 48000 then $rig.spectrum 2048, 2.0
|
14
|
+
when $rig.rate <= 96000 then $rig.spectrum 2048, 4.0
|
15
|
+
else $rig.spectrum 2048, 8.0
|
16
|
+
end
|
17
|
+
@response.body = [Radio::Gif.waterfall($waterfall_gradient, [spectrum])]
|
18
|
+
@response.headers['Content-Type'] = 'image/gif'
|
19
|
+
@response.headers["Cache-Control"] = 'max-age=0, private, must-revalidate'
|
20
|
+
%>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: radio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,24 +9,88 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
12
|
+
date: 2012-02-14 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: fftw3
|
16
|
+
requirement: &2198866920 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2198866920
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: thin
|
27
|
+
requirement: &2198866220 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2198866220
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: libusb
|
38
|
+
requirement: &2198865360 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2198865360
|
14
47
|
description:
|
15
48
|
email:
|
16
49
|
- dturnbull@gmail.com
|
17
|
-
executables:
|
50
|
+
executables:
|
51
|
+
- radio-server
|
18
52
|
extensions: []
|
19
53
|
extra_rdoc_files: []
|
20
54
|
files:
|
55
|
+
- bin/radio-server
|
56
|
+
- lib/radio/controls/null.rb
|
57
|
+
- lib/radio/controls/si570avr.rb
|
58
|
+
- lib/radio/filter.rb
|
59
|
+
- lib/radio/filters/fir.rb
|
60
|
+
- lib/radio/gif.rb
|
61
|
+
- lib/radio/http/file.rb
|
62
|
+
- lib/radio/http/script.rb
|
63
|
+
- lib/radio/http/server.rb
|
64
|
+
- lib/radio/http/session.rb
|
65
|
+
- lib/radio/input.rb
|
66
|
+
- lib/radio/inputs/alsa.rb
|
67
|
+
- lib/radio/inputs/coreaudio.rb
|
68
|
+
- lib/radio/inputs/file.rb
|
69
|
+
- lib/radio/inputs/wav.rb
|
21
70
|
- lib/radio/psk31/bit_detect.rb
|
22
71
|
- lib/radio/psk31/decoder.rb
|
23
|
-
- lib/radio/psk31/filters.rb
|
24
72
|
- lib/radio/psk31/fir_coef.rb
|
25
73
|
- lib/radio/psk31/rx.rb
|
26
74
|
- lib/radio/psk31/varicode.rb
|
75
|
+
- lib/radio/rig/lo.rb
|
76
|
+
- lib/radio/rig/rx.rb
|
77
|
+
- lib/radio/rig/spectrum.rb
|
78
|
+
- lib/radio/rig.rb
|
79
|
+
- lib/radio/version.rb
|
27
80
|
- lib/radio.rb
|
81
|
+
- www/index.erb
|
82
|
+
- www/jquery-1.7.js
|
83
|
+
- www/lo.erb
|
84
|
+
- www/setup/input.erb
|
85
|
+
- www/setup/lo.erb
|
86
|
+
- www/waterfall.erb
|
28
87
|
- README.md
|
29
|
-
|
88
|
+
- LICENSE
|
89
|
+
- test/test.rb
|
90
|
+
- test/wav/bpsk8k.wav
|
91
|
+
- test/wav/qpsk8k.wav
|
92
|
+
- test/wav/ssb.wav
|
93
|
+
homepage: https://github.com/ham21/radio
|
30
94
|
licenses: []
|
31
95
|
post_install_message:
|
32
96
|
rdoc_options: []
|
@@ -46,9 +110,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
110
|
version: '0'
|
47
111
|
requirements: []
|
48
112
|
rubyforge_project:
|
49
|
-
rubygems_version: 1.8.
|
113
|
+
rubygems_version: 1.8.10
|
50
114
|
signing_key:
|
51
115
|
specification_version: 3
|
52
|
-
summary: Amateur
|
53
|
-
test_files:
|
116
|
+
summary: The Twenty-First Century Amateur Radio Project
|
117
|
+
test_files:
|
118
|
+
- test/test.rb
|
119
|
+
- test/wav/bpsk8k.wav
|
120
|
+
- test/wav/qpsk8k.wav
|
121
|
+
- test/wav/ssb.wav
|
54
122
|
has_rdoc:
|
data/lib/radio/psk31/filters.rb
DELETED
@@ -1,220 +0,0 @@
|
|
1
|
-
class Radio
|
2
|
-
|
3
|
-
class PSK31
|
4
|
-
|
5
|
-
# An instance of Filters handles everything from 48kHz to 500Hz.
|
6
|
-
# PSK31/PSK63/PSK125 emit at 500Hz/1000Hz/2000Hz respectively.
|
7
|
-
|
8
|
-
class Filters
|
9
|
-
|
10
|
-
attr_accessor :frequency
|
11
|
-
attr_accessor :clock # 8000.0 +/-
|
12
|
-
attr_accessor :phase_inc
|
13
|
-
attr_accessor :speed # 31 | 63 | 125
|
14
|
-
|
15
|
-
# Format of the input data stream is specified in the same
|
16
|
-
# format as String#unpack. Here are some examples:
|
17
|
-
# 'C' 8-bit unsigned mono
|
18
|
-
# 'xxv' Little-endian 16-bit right channel
|
19
|
-
# Not everything is supported outside this native Ruby implementation.
|
20
|
-
# The following are guaranteed to be in a C or Java implementation.
|
21
|
-
# x - ignores a byte (in an unused channel)
|
22
|
-
# C/c - Unsigned/signed bytes
|
23
|
-
# n/v - Unsigned 16-bit words in big/little endian format
|
24
|
-
|
25
|
-
# You must supply at least one of the dec16, dec8, or dec4 filters and
|
26
|
-
# it must be appropriate for the speed you desire. The dec4 filter can
|
27
|
-
# be used for all speeds, dec8 only for PSK63, and dec16 only for PSK31.
|
28
|
-
|
29
|
-
def initialize sample_rate, format, frequency, filters
|
30
|
-
@do_dec6 = case sample_rate
|
31
|
-
when 8000 then false
|
32
|
-
when 48000 then true
|
33
|
-
else raise 'only 8000 and 48000 Hz sample rates are supported'
|
34
|
-
end
|
35
|
-
@format = format
|
36
|
-
@sample_size = [0].pack(format).size
|
37
|
-
case ("\x80"*16).unpack(format)[0]
|
38
|
-
when 128
|
39
|
-
@max = 128
|
40
|
-
@offset = -128
|
41
|
-
when -128
|
42
|
-
@max = 128
|
43
|
-
@offset = 0
|
44
|
-
when 32768 + 128
|
45
|
-
@max = 32768
|
46
|
-
@offset = -32768
|
47
|
-
when -32768 + 128
|
48
|
-
@max = 32768
|
49
|
-
@offset = 0
|
50
|
-
else
|
51
|
-
raise 'unable to interpret format'
|
52
|
-
end
|
53
|
-
@frequency = frequency
|
54
|
-
@clock = 8000.0
|
55
|
-
@phase = 0.0
|
56
|
-
@speed = 31
|
57
|
-
@pulse = 0
|
58
|
-
if filters[:dec6]
|
59
|
-
@dec6_coef = NArray.to_na filters[:dec6]*2
|
60
|
-
@dec6_data = NArray.float filters[:dec6].size
|
61
|
-
@dec6_pos = 0
|
62
|
-
@dec6_pulse = 6
|
63
|
-
elsif @do_dec6
|
64
|
-
raise 'no 48000 Hz filter found'
|
65
|
-
end
|
66
|
-
if filters[:dec16]
|
67
|
-
@dec16_coef = NArray.to_na filters[:dec16]*2
|
68
|
-
@dec16_sin = NArray.float filters[:dec16].size
|
69
|
-
@dec16_cos = NArray.float filters[:dec16].size
|
70
|
-
@dec16_pos = 0
|
71
|
-
else
|
72
|
-
@dec16_coef = nil
|
73
|
-
end
|
74
|
-
if filters[:dec8]
|
75
|
-
@dec8_coef = NArray.to_na filters[:dec8]*2
|
76
|
-
@dec8_sin = NArray.float filters[:dec8].size
|
77
|
-
@dec8_cos = NArray.float filters[:dec8].size
|
78
|
-
@dec8_pos = 0
|
79
|
-
else
|
80
|
-
@dec8_coef = nil
|
81
|
-
end
|
82
|
-
if filters[:dec4]
|
83
|
-
@dec4_coef = NArray.to_na filters[:dec4]*2
|
84
|
-
@dec4a_sin = NArray.float filters[:dec4].size
|
85
|
-
@dec4a_cos = NArray.float filters[:dec4].size
|
86
|
-
@dec4a_pos = 0
|
87
|
-
@dec4b_sin = NArray.float filters[:dec4].size
|
88
|
-
@dec4b_cos = NArray.float filters[:dec4].size
|
89
|
-
@dec4b_pos = 0
|
90
|
-
else
|
91
|
-
@dec4_coef = nil
|
92
|
-
end
|
93
|
-
@bit_coef = NArray.to_na filters[:bit]*2
|
94
|
-
@bit_sin = NArray.float filters[:bit].size
|
95
|
-
@bit_cos = NArray.float filters[:bit].size
|
96
|
-
@bit_pos = 0
|
97
|
-
recalc_phase_inc
|
98
|
-
end
|
99
|
-
|
100
|
-
def reset
|
101
|
-
if @dec6_coef
|
102
|
-
@dec6_data.fill 0.0
|
103
|
-
end
|
104
|
-
if @dec16_coef
|
105
|
-
@dec16_sin_data.fill 0.0
|
106
|
-
@dec16_cos_data.fill 0.0
|
107
|
-
end
|
108
|
-
if @dec8_coef
|
109
|
-
@dec8_sin_data.fill 0.0
|
110
|
-
@dec8_cos_data.fill 0.0
|
111
|
-
end
|
112
|
-
if @dec4_coef
|
113
|
-
@dec4a_sin.fill 0.0
|
114
|
-
@dec4a_cos.fill 0.0
|
115
|
-
@dec4b_sin.fill 0.0
|
116
|
-
@dec4b_cos.fill 0.0
|
117
|
-
end
|
118
|
-
@bit_sin.fill 0.0
|
119
|
-
@bit_cos.fill 0.0
|
120
|
-
end
|
121
|
-
|
122
|
-
def recalc_phase_inc
|
123
|
-
@phase_inc = PI2 * @frequency / @clock
|
124
|
-
end
|
125
|
-
|
126
|
-
def call sample_data
|
127
|
-
raise 'alignment error' unless sample_data.size % @sample_size == 0
|
128
|
-
sample_data.force_encoding('binary') # Ensure slice is fast like Ruby 1.9.3 byteslice
|
129
|
-
mod16_8 = @speed == 63 ? 8 : 16
|
130
|
-
pos = 0
|
131
|
-
while pos < sample_data.size
|
132
|
-
pos += @sample_size
|
133
|
-
sample = sample_data.slice(pos,@sample_size).unpack(@format)[0] || 0
|
134
|
-
sample = (sample + @offset).to_f / @max
|
135
|
-
if @do_dec6
|
136
|
-
@dec6_pos = @dec6_data.size if @dec6_pos == 0
|
137
|
-
@dec6_pos -= 1
|
138
|
-
@dec6_data[@dec6_pos] = sample
|
139
|
-
@dec6_pulse -= 1
|
140
|
-
next unless @dec6_pulse == 0
|
141
|
-
@dec6_pulse = 6
|
142
|
-
sample = @dec6_data.fir(@dec6_coef, @dec6_pos)
|
143
|
-
end
|
144
|
-
@phase += @phase_inc
|
145
|
-
@phase -= PI2 if @phase > PI2
|
146
|
-
if @dec16_coef and @speed == 31
|
147
|
-
@dec16_pos = @dec16_sin.size if @dec16_pos == 0
|
148
|
-
@dec16_pos -= 1
|
149
|
-
@dec16_sin[@dec16_pos] = sample * Math.sin(@phase)
|
150
|
-
@dec16_cos[@dec16_pos] = sample * Math.cos(@phase)
|
151
|
-
next unless ((@pulse = @pulse + 1 & 0xFF) % 16) == 0
|
152
|
-
ival = @dec16_sin.fir(@dec16_coef, @dec16_pos)
|
153
|
-
qval = @dec16_cos.fir(@dec16_coef, @dec16_pos)
|
154
|
-
elsif @dec8_coef and @speed == 63
|
155
|
-
@dec8_pos = @dec8_sin.size if @dec8_pos == 0
|
156
|
-
@dec8_pos -= 1
|
157
|
-
@dec8_sin[@dec8_pos] = sample * Math.sin(@phase)
|
158
|
-
@dec8_cos[@dec8_pos] = sample * Math.cos(@phase)
|
159
|
-
next unless ((@pulse = @pulse + 1 & 0xFF) % 8) == 0
|
160
|
-
ival = @dec8_sin.fir(@dec8_coef, @dec8_pos)
|
161
|
-
qval = @dec8_cos.fir(@dec8_coef, @dec8_pos)
|
162
|
-
elsif @dec4_coef
|
163
|
-
@dec4a_pos = @dec4a_sin.size if @dec4a_pos == 0
|
164
|
-
@dec4a_pos -= 1
|
165
|
-
@dec4a_sin[@dec4a_pos] = sample * Math.sin(@phase)
|
166
|
-
@dec4a_cos[@dec4a_pos] = sample * Math.cos(@phase)
|
167
|
-
next unless ((@pulse = @pulse + 1 & 0xFF) % 4) == 0
|
168
|
-
@dec4b_pos = @dec4b_sin.size if @dec4b_pos == 0
|
169
|
-
@dec4b_pos -= 1
|
170
|
-
ival = @dec4b_sin[@dec4b_pos] = @dec4a_sin.fir(@dec4_coef, @dec4a_pos)
|
171
|
-
qval = @dec4b_cos[@dec4b_pos] = @dec4a_cos.fir(@dec4_coef, @dec4a_pos)
|
172
|
-
next unless @speed == 125 or (@pulse % mod16_8 == 0)
|
173
|
-
unless @speed == 125
|
174
|
-
ival = @dec4b_sin.fir(@dec4_coef, @dec4b_pos)
|
175
|
-
qval = @dec4b_cos.fir(@dec4_coef, @dec4b_pos)
|
176
|
-
end
|
177
|
-
else
|
178
|
-
raise 'no suitable filter found'
|
179
|
-
end
|
180
|
-
@bit_pos = @bit_sin.size if @bit_pos == 0
|
181
|
-
@bit_pos -= 1
|
182
|
-
@bit_sin[@bit_pos] = ival
|
183
|
-
@bit_cos[@bit_pos] = qval
|
184
|
-
yield @bit_sin.fir(@bit_coef, @bit_pos), @bit_cos.fir(@bit_coef, @bit_pos)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
# NArray can easily double filter performance
|
189
|
-
begin
|
190
|
-
require 'narray'
|
191
|
-
class ::NArray
|
192
|
-
def fir filter, pos
|
193
|
-
(self * filter[size-pos..-1-pos]).sum
|
194
|
-
end
|
195
|
-
end
|
196
|
-
rescue LoadError => e
|
197
|
-
# Pure Ruby fake NArray
|
198
|
-
class NArray < Array
|
199
|
-
def self.float arg
|
200
|
-
new arg, 0.0
|
201
|
-
end
|
202
|
-
def self.to_na arg
|
203
|
-
new(arg).freeze
|
204
|
-
end
|
205
|
-
def fir filter, pos
|
206
|
-
acc = 0.0
|
207
|
-
index = size - pos
|
208
|
-
each do |val|
|
209
|
-
acc += val * filter[index]
|
210
|
-
index += 1
|
211
|
-
end
|
212
|
-
acc
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|