radio 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,39 @@
1
+ # Copyright 2012 The ham21/radio Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ class Radio
17
+
18
+ PI = Math::PI.freeze
19
+ PI2 = (8.0 * Math.atan(1.0)).freeze
20
+
21
+ module Utils
22
+
23
+ def kaiser_estimate options
24
+ ripple = options[:passband].to_f * options[:stopband]
25
+ numer = -20.0 * Math.log10(ripple) - 13
26
+ denum = 14.6 * options[:transition]
27
+ taps = (numer/denum).round
28
+ type = options[:type] || :odd
29
+ if type == :even
30
+ taps +=1 if taps.odd?
31
+ else
32
+ taps +=1 if taps.even?
33
+ end
34
+ taps
35
+ end
36
+ module_function :kaiser_estimate
37
+
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright 2012 The ham21/radio Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ class Radio
17
+
18
+ module Utils
19
+
20
+ def hamming_window! array, width = nil
21
+ n = -1
22
+ width ||= array.size
23
+ w = width - 1
24
+ array.collect! do |v|
25
+ n += 1
26
+ 0.54 - 0.46 * Math.cos((PI2 * n) / w)
27
+ end
28
+ end
29
+ module_function :hamming_window!
30
+
31
+ def hamming_window array, w = nil
32
+ hamming_window! array.dup
33
+ end
34
+ module_function :hamming_window
35
+
36
+ end
37
+ end
@@ -1,3 +1,3 @@
1
1
  class Radio
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
@@ -1,29 +1,98 @@
1
- <% if !$rig; response.redirect 'setup/input'; else
1
+ <% if !$rig; response.redirect 'setup/rx'; else
2
2
  -%><!DOCTYPE html>
3
3
  <html>
4
4
  <head>
5
5
  <style type="text/css" media="screen">
6
- body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}
6
+ body{font:13px/1.231 arial,helvetica,clean,sans-serif;
7
+ *font-size:small;*font:x-small;background:#fff}
7
8
  select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}
8
9
  img{display:block}
9
- #waterfall{height: 75px; width: 95%; overflow-x:scroll; overflow-y: hidden; background:#000}
10
+ #waterfallxx{height: 75px; width: 95%; overflow-x:scroll; overflow-y: hidden; background:#000}
11
+ #main{
12
+ background:#D36B01;
13
+ color:#fff;
14
+ width:940px;
15
+ margin:auto;
16
+ -moz-border-radius: 10px;
17
+ border-radius: 10px;
18
+ padding: 3px 10px 10px 10px;
19
+ }
20
+ #title {
21
+ font-size:36px;
22
+ font-weight:bold;
23
+ text-align:center;
24
+ }
25
+ #main a:link, #title a:visited, #title a:link, #title a:link {
26
+ text-decoration:none; color:#fff
27
+ }
28
+ #waterfall{
29
+ }
30
+ #output{
31
+ background:#fcfcfc;
32
+ color:#000;
33
+ height:400px;
34
+ overflow-x: hidden;
35
+ overflow-y: scroll;
36
+ }
37
+ #marker{
38
+ position:absolute;
39
+ left:-10px;
40
+ top:20px;
41
+ z-index:5;
42
+ background:#13D205;
43
+ width:10px;
44
+ height:10px;
45
+ -moz-border-radius: 10px;
46
+ border-radius: 10px;
47
+ }
48
+ #wrap{
49
+ position:relative;
50
+ height: 100px;
51
+ width: 940px;
52
+ overflow-x: scroll;
53
+ overflow-y: hidden;
54
+ background:#000
55
+ }
10
56
  </style>
11
57
  <script src='jquery-1.7.js'></script>
12
58
  </head>
13
59
  <body>
60
+ <div id="main">
61
+ <div id="title">
62
+ <a href="https://www.github.com/ham21/radio" target="_blank">
63
+ The Twenty-First Century Amateur Radio Project
64
+ </a>
65
+ </div>
66
+
67
+ <div id="wrap">
68
+ <div id="marker"></div>
69
+ <div id="waterfall"></div>
70
+ </div>
71
+
72
+ <div style="float:right;">
73
+ <%= render 'ssb' %>
74
+ </div>
75
+ <%= render 'lo' %>
76
+
77
+ <div id="output">
78
+ </div>
14
79
 
15
- <h2>
16
- <a href="https://github.com/ham21/radio">Ham21</a>
17
- - The Twenty-First Century Amateur Radio Project
18
- </h2>
19
- <p>SETUP: <a href="setup/input">Input</a> | <a href="setup/lo">LO</a></p>
20
-
21
- <%= render 'lo' %>
22
-
23
- <div id="waterfall">
24
80
  </div>
81
+
82
+ <p style="text-align:center">
83
+ SETUP: <a href="setup/rx">RX</a> | <a href="setup/af">AF</a> | <a href="setup/lo">LO</a>
84
+ </p>
85
+
25
86
 
26
87
  <script type="text/javascript" charset="utf-8">
88
+ $("#waterfall").mousedown(function(event) {
89
+ console.log(event);
90
+ pos = event.offsetX / $("#waterfall").children()[1].width
91
+ $.post( 'tune', { pos: pos });
92
+ $("#marker")[0].style.left = '' + (event.offsetX - 5) + 'px';
93
+ });
94
+
95
+
27
96
  var waterfallSeqNo = 0;
28
97
  function nextWaterfall() {
29
98
  $('#waterfall').prepend('<img src="waterfall?' + waterfallSeqNo + '" alt="" onload="nextWaterfall()"></img>');
data/www/lo.erb CHANGED
@@ -4,7 +4,7 @@
4
4
  @response.headers['Content-Type'] = 'text/plain'
5
5
  end -%>
6
6
  <form action="lo" id="freqForm">
7
- <input type="text" name="freq" value="<%= $rig.lo %>" %>
7
+ <input type="text" name="freq" value="<%= $rig.lo %>" %> MHz
8
8
  </form>
9
9
  <script type="text/javascript">
10
10
  $("#freqForm").submit(function(event) {
@@ -17,5 +17,5 @@ end -%>
17
17
  $form.find( 'input[name="freq"]' ).val(data)
18
18
  }
19
19
  );
20
- });
20
+ });
21
21
  </script>
@@ -0,0 +1,72 @@
1
+ <%
2
+ if params['doit']
3
+ if params['type'] == 'none'
4
+ $rig.af = nil
5
+ else
6
+ $rig.af = Radio::Signal.new type:params['type'], id:params['id'], rate:params['rate'].to_i, output:true
7
+ end
8
+ response.redirect '/'
9
+ elsif params['type']
10
+ %>
11
+ <!DOCTYPE html>
12
+ <html>
13
+ <head>
14
+ <meta http-equiv="refresh" content="0; <%=h '?doit=1&' + query_string %>">
15
+ </head>
16
+ <body>
17
+ <p><strong>Stand by, generating coefficients and compiling filter.</strong></p>
18
+ This may take many minutes.<br />
19
+ Results are cached in: <%=h Radio::Utils::FIRPM_CACHE_FILENAME %>
20
+ </body>
21
+ </html>
22
+ <% else -%>
23
+ <!DOCTYPE html>
24
+ <html>
25
+ <head>
26
+ <style type="text/css" media="screen">
27
+ body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}
28
+ select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}
29
+ </style>
30
+ </head>
31
+ <body>
32
+
33
+ <h2>Audio Output Sources</h2>
34
+ <% if (input_sources = Radio::Signal.devices.delete_if{|k,v|v[:output]==0}).empty? -%>
35
+ No input sources found.
36
+ <% else -%>
37
+ <dl>
38
+ <form action='?' method="get">
39
+ <dt>
40
+ <input type="submit" value="Select"%>
41
+ <input type="hidden" name="type" value="none" %>
42
+ No output: stop processing audio
43
+ </dt>
44
+ </form>
45
+ <% input_sources.each do |k, opts| -%>
46
+ <form action='?' method="get">
47
+ <% input_type, input_id = k -%>
48
+ <dt>
49
+ <input type="submit" value="Select"%>
50
+ <input type="hidden" name="type" value="<%=h input_type %>" %>
51
+ <input type="hidden" name="id" value="<%=h input_id %>" %>
52
+ <%=h input_type %>: <%=h opts[:name] %>
53
+ </dt>
54
+ <dd>
55
+ <% opts[:rates].reverse.each_with_index do |rate, index| %>
56
+ <input type="radio" name="rate" value="<%=h rate %>" <%= "checked=checked" if index==0 %> /><%=h rate %>
57
+ <% end -%>
58
+ </dd>
59
+ </form>
60
+ <br />
61
+ <% end -%>
62
+ </dl>
63
+ <% end -%>
64
+
65
+ <h2>Driver Status</h2>
66
+ <% Radio::Signal.status.each do |k, v| -%>
67
+ <%=h k %>: <%=h v %> <br />
68
+ <% end -%>
69
+
70
+ </body>
71
+ </html>
72
+ <% end -%>
@@ -2,6 +2,13 @@
2
2
  if post?
3
3
  $rig.lo = case params['type']
4
4
  when 'softrock' then Radio::Controls::Si570AVR.new
5
+ when 'civ'
6
+ Radio::Controls::CIV.new({
7
+ port:params['port'],
8
+ baud:params['baud'],
9
+ host:params['host'],
10
+ device:params['device'],
11
+ })
5
12
  else Radio::Controls::Null.new
6
13
  end
7
14
  response.redirect '/'
@@ -30,6 +37,30 @@ unless response.redirection? -%>
30
37
  SoftRock Si570 (DG8SAQ/PE0FKO)
31
38
  </form>
32
39
  <br />
40
+ <form action='?' method="post">
41
+ <input type="submit" value="Select"%>
42
+ <input type="hidden" name="type" value="civ" %>
43
+ Icom CI-V (supports CT-17 and RS-422 multi-drop)
44
+ <br/>
45
+ Port:
46
+ <select name="port">
47
+ <% 0.upto(7) do |num| -%>
48
+ <option value="<%=h num %>"><%=h num %></option>
49
+ <% end -%>
50
+ </select>
51
+ Baud:
52
+ <select name="baud">
53
+ <% [300,1200,9600,19200].each do |num| -%>
54
+ <option value="<%=h num %>" <%= 'selected="selected"' if num==1200 %>><%=h num %></option>
55
+ <% end -%>
56
+ </select>
57
+ Host:
58
+ <input type="text" name="host" value="224"%>
59
+ Device:
60
+ <input type="text" name="device" value="80" %>
61
+
62
+ </form>
63
+ <br />
33
64
 
34
65
  </body>
35
66
  </html>
@@ -1,12 +1,13 @@
1
1
  <%
2
2
  if post?
3
3
  $rig ||= Radio::Rig.new
4
- channel_i, channel_q = case params['channel']
4
+ device = case params['channel']
5
5
  when 'iq' then [0,1]
6
6
  when 'qi' then [1,0]
7
- else [0,nil]
7
+ else 0
8
8
  end
9
- $rig.rx = Radio::Input.new params['type'], params['id'], params['rate'].to_i, channel_i, channel_q
9
+ $rig.af = nil
10
+ $rig.rx = Radio::Signal.new type:params['type'], id:params['id'], rate:params['rate'].to_i, input:device
10
11
  response.redirect '/'
11
12
  end
12
13
  unless response.redirection? -%>
@@ -20,8 +21,8 @@ unless response.redirection? -%>
20
21
  </head>
21
22
  <body>
22
23
 
23
- <h2>Input Sources</h2>
24
- <% if (input_sources = Radio::Input.sources).empty? -%>
24
+ <h2>Radio Input Sources</h2>
25
+ <% if (input_sources = Radio::Signal.devices.delete_if{|k,v|v[:input]==0}).empty? -%>
25
26
  No input sources found.
26
27
  <% else -%>
27
28
  <dl>
@@ -40,12 +41,12 @@ unless response.redirection? -%>
40
41
  <% end -%>
41
42
  </dd>
42
43
  <dd>
43
- <% if opts[:channels] == 1 or input_type != :File %>
44
+ <% if opts[:input] == 1 or input_type != :File %>
44
45
  <input type="radio" name="channel" value="i" checked="checked" />LPCM
45
46
  <% 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
47
+ <% if opts[:input] == 2 %>
48
+ <input type="radio" name="channel" value="iq" checked="checked" />I/Q
49
+ <input type="radio" name="channel" value="qi" />Q/I
49
50
  <% end -%>
50
51
  </dd>
51
52
  </form>
@@ -55,7 +56,7 @@ unless response.redirection? -%>
55
56
  <% end -%>
56
57
 
57
58
  <h2>Driver Status</h2>
58
- <% Radio::Input.status.each do |k, v| -%>
59
+ <% Radio::Signal.status.each do |k, v| -%>
59
60
  <%=h k %>: <%=h v %> <br />
60
61
  <% end -%>
61
62
 
@@ -0,0 +1,20 @@
1
+ <% if xhr?
2
+ if params['ssb'] == 'lsb'
3
+ $rig.set_lsb
4
+ else
5
+ $rig.set_usb
6
+ end
7
+ end -%>
8
+ <form action="ssb" id="ssbForm">
9
+ <input type="radio" name="ssb" value="lsb" %> LSB
10
+ <input type="radio" name="ssb" value="usb" %> USB
11
+ </form>
12
+ <script type="text/javascript">
13
+ $("#ssbForm input").change(function(event) {
14
+ event.preventDefault();
15
+ var $form = $( this ),
16
+ term = $form.val(),
17
+ url = $form.attr( 'action' );
18
+ $.post( url, { ssb: term });
19
+ });
20
+ </script>
@@ -0,0 +1,5 @@
1
+ <%
2
+ i = params['pos'].to_f
3
+ i -= 0.5 if $rig.iq?
4
+ $rig.tune = -i * $rig.rate
5
+ %>
@@ -14,7 +14,7 @@ when $rig.rate <= 48000 then $rig.spectrum 2048, 2.0
14
14
  when $rig.rate <= 96000 then $rig.spectrum 2048, 4.0
15
15
  else $rig.spectrum 2048, 8.0
16
16
  end
17
- @response.body = [Radio::Gif.waterfall($waterfall_gradient, [spectrum])]
17
+ @response.body = [Radio::Gif.waterfall($waterfall_gradient, spectrum.reshape(spectrum.size,1))]
18
18
  @response.headers['Content-Type'] = 'image/gif'
19
19
  @response.headers["Cache-Control"] = 'max-age=0, private, must-revalidate'
20
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.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-14 00:00:00.000000000Z
12
+ date: 2012-05-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fftw3
16
- requirement: &2198866920 !ruby/object:Gem::Requirement
16
+ requirement: &70250569804720 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2198866920
24
+ version_requirements: *70250569804720
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: thin
27
- requirement: &2198866220 !ruby/object:Gem::Requirement
27
+ requirement: &70250569803780 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2198866220
35
+ version_requirements: *70250569803780
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: libusb
38
- requirement: &2198865360 !ruby/object:Gem::Requirement
38
+ requirement: &70250569802740 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,18 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *2198865360
46
+ version_requirements: *70250569802740
47
+ - !ruby/object:Gem::Dependency
48
+ name: serialport
49
+ requirement: &70250569801620 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70250569801620
47
58
  description:
48
59
  email:
49
60
  - dturnbull@gmail.com
@@ -53,43 +64,49 @@ extensions: []
53
64
  extra_rdoc_files: []
54
65
  files:
55
66
  - bin/radio-server
67
+ - lib/radio/controls/civ.rb
56
68
  - lib/radio/controls/null.rb
57
69
  - lib/radio/controls/si570avr.rb
58
70
  - lib/radio/filter.rb
71
+ - lib/radio/filters/agc.rb
59
72
  - lib/radio/filters/fir.rb
73
+ - lib/radio/filters/iq.rb
60
74
  - lib/radio/gif.rb
61
75
  - lib/radio/http/file.rb
62
76
  - lib/radio/http/script.rb
63
77
  - lib/radio/http/server.rb
64
78
  - 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
70
79
  - lib/radio/psk31/bit_detect.rb
71
80
  - lib/radio/psk31/decoder.rb
72
- - lib/radio/psk31/fir_coef.rb
73
81
  - lib/radio/psk31/rx.rb
74
82
  - lib/radio/psk31/varicode.rb
75
83
  - lib/radio/rig/lo.rb
76
84
  - lib/radio/rig/rx.rb
77
85
  - lib/radio/rig/spectrum.rb
86
+ - lib/radio/rig/ssb.rb
87
+ - lib/radio/rig/ssb.rb_
78
88
  - lib/radio/rig.rb
89
+ - lib/radio/signal.rb
90
+ - lib/radio/signals/alsa.rb
91
+ - lib/radio/signals/coreaudio.rb
92
+ - lib/radio/signals/file.rb
93
+ - lib/radio/signals/wav.rb
94
+ - lib/radio/utils/firpm.rb
95
+ - lib/radio/utils/misc.rb
96
+ - lib/radio/utils/window.rb
79
97
  - lib/radio/version.rb
80
98
  - lib/radio.rb
81
99
  - www/index.erb
82
100
  - www/jquery-1.7.js
83
101
  - www/lo.erb
84
- - www/setup/input.erb
102
+ - www/setup/af.erb
85
103
  - www/setup/lo.erb
104
+ - www/setup/rx.erb
105
+ - www/ssb.erb
106
+ - www/tune.erb
86
107
  - www/waterfall.erb
87
108
  - README.md
88
109
  - LICENSE
89
- - test/test.rb
90
- - test/wav/bpsk8k.wav
91
- - test/wav/qpsk8k.wav
92
- - test/wav/ssb.wav
93
110
  homepage: https://github.com/ham21/radio
94
111
  licenses: []
95
112
  post_install_message:
@@ -110,13 +127,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
127
  version: '0'
111
128
  requirements: []
112
129
  rubyforge_project:
113
- rubygems_version: 1.8.10
130
+ rubygems_version: 1.8.15
114
131
  signing_key:
115
132
  specification_version: 3
116
133
  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
122
- has_rdoc:
134
+ test_files: []