0
|
1 ???using System; |
|
2 using System.Collections.Generic; |
|
3 |
|
4 namespace UCIS.Radio { |
|
5 public struct TunerFrequencyRange { |
|
6 public TunerFrequencyRange(ulong Begin, ulong End) { |
|
7 this.Begin = Begin; |
|
8 this.End = End; |
|
9 } |
|
10 |
|
11 public ulong Begin; |
|
12 public ulong End; |
|
13 } |
|
14 public struct TunerMode { |
|
15 public TunerMode(int Index, string Name) { |
|
16 this.Index = Index; |
|
17 this.Name = Name; |
|
18 } |
|
19 |
|
20 public int Index; |
|
21 public string Name; |
|
22 } |
|
23 public struct TunerFilter { |
|
24 public TunerFilter(int Index, string Name) { |
|
25 this.Index = Index; |
|
26 this.Name = Name; |
|
27 } |
|
28 |
|
29 public int Index; |
|
30 public string Name; |
|
31 } |
|
32 |
|
33 public class TunerCapabilities { |
|
34 public TunerFrequencyRange[] Bands = new TunerFrequencyRange[0]; |
|
35 public IDictionary<byte, string> Modes = new Dictionary<byte, string>(); |
|
36 public IDictionary<byte, string> Filters = new Dictionary<byte, string>(); |
|
37 public IList<TunerOption> Options = new List<TunerOption>(); |
|
38 public byte[] AvailableModes; |
|
39 public byte[] AvailableFilters; |
|
40 } |
|
41 |
|
42 public enum TunerOption : byte { |
|
43 //R/W 0-255 value |
|
44 Volume = 1, |
|
45 Squelch = 2, |
|
46 IfShift = 3, |
|
47 |
|
48 //Not accessible (feature indication only) |
|
49 Frequency = 50, |
|
50 Mode = 51, |
|
51 Filter = 52, |
|
52 |
|
53 //Read only |
|
54 Signal = 70, |
|
55 Online = 71, |
|
56 |
|
57 //R/W On/Off |
|
58 Attenuator = 100, |
|
59 AGC = 101, |
|
60 NoiseBlanker = 102, |
|
61 VSC = 103, |
|
62 StereoMono = 104, |
|
63 |
|
64 //W Execute |
|
65 Poll = 151, |
|
66 RadioText = 200, |
|
67 |
|
68 //200+: reserved for personal use |
|
69 } |
|
70 |
|
71 public class TunerOptionChangedEventArgs : EventArgs { |
|
72 public TunerOptionChangedEventArgs(TunerOption option) { Option = option; } |
|
73 public TunerOption Option; |
|
74 } |
|
75 |
|
76 public interface ITuner { |
|
77 event EventHandler TuningChanged; |
|
78 event EventHandler<TunerOptionChangedEventArgs> OptionChanged; |
|
79 void Open(); |
|
80 void Close(); |
|
81 void Poll(); |
|
82 TunerCapabilities Capabilities { get; } |
|
83 ulong Frequency { get; set; } |
|
84 byte Mode { get; set; } |
|
85 byte Filter { get; set; } |
|
86 bool SetTuning(ulong frequency, byte mode, byte filter); |
|
87 bool SetOption(TunerOption Option, byte Value); |
|
88 byte GetOption(TunerOption Option); |
|
89 } |
|
90 |
|
91 public abstract class Tuner : ITuner { |
|
92 private ulong _frequency; |
|
93 private byte _mode, _filter; |
|
94 private TunerCapabilities _capabilities = new TunerCapabilities(); |
|
95 private byte[] _options = new byte[256]; |
|
96 |
|
97 public event EventHandler TuningChanged; |
|
98 public event EventHandler AvailableModesChanged; |
|
99 public event EventHandler<TunerOptionChangedEventArgs> OptionChanged; |
|
100 |
|
101 protected Tuner() { |
|
102 //AcceptOption(ReceiverOptions.IfShift, 127); |
|
103 //AcceptOption(ReceiverOptions.Online, 1); |
|
104 } |
|
105 |
|
106 public virtual void Open() { } |
|
107 public virtual void Close() { } |
|
108 public virtual void Poll() { } |
|
109 |
|
110 public TunerCapabilities Capabilities { get { return _capabilities; } } |
|
111 |
|
112 public ulong Frequency { |
|
113 get { return _frequency; } |
|
114 set {SetTuning(value, 0, 0); } |
|
115 } |
|
116 public byte Mode { |
|
117 get { return _mode; } |
|
118 set { SetTuning(0, value, 0); } |
|
119 } |
|
120 public byte Filter { |
|
121 get { return _mode; } |
|
122 set { SetTuning(0, 0, value); } |
|
123 } |
|
124 public virtual bool SetTuning(ulong frequency, byte mode, byte filter) { |
|
125 return SetTuning(ref frequency, ref mode, ref filter); |
|
126 } |
|
127 public virtual bool SetTuning(ref ulong frequency, ref byte mode, ref byte filter) { |
|
128 bool notexact = false; |
|
129 CheckFrequency(ref frequency, ref notexact); |
|
130 CheckMode(ref mode, ref notexact); |
|
131 CheckFilter(ref filter, ref notexact); |
|
132 AcceptTuning(frequency, mode, filter); |
|
133 return !notexact; |
|
134 } |
|
135 |
|
136 public virtual bool SetOption(TunerOption Option, byte Value) { |
|
137 return SetOption(Option, ref Value); |
|
138 } |
|
139 public virtual bool SetOption(TunerOption Option, ref byte Value) { |
|
140 bool notexact = false; |
|
141 CheckOption(Option, ref Value, ref notexact); |
|
142 AcceptOption(Option, Value); |
|
143 return !notexact; |
|
144 } |
|
145 public virtual byte GetOption(TunerOption Option) { |
|
146 return _options[(int)Option]; |
|
147 } |
|
148 protected bool CheckOption(TunerOption Option, ref byte Value, ref bool notexact) { |
|
149 switch (Option) { |
|
150 case TunerOption.Filter: |
|
151 case TunerOption.Frequency: |
|
152 case TunerOption.Mode: |
|
153 case TunerOption.Signal: |
|
154 Value = 0; |
|
155 notexact = true; |
|
156 return false; |
|
157 case TunerOption.AGC: |
|
158 case TunerOption.Attenuator: |
|
159 case TunerOption.NoiseBlanker: |
|
160 case TunerOption.StereoMono: |
|
161 case TunerOption.VSC: |
|
162 if (Value > 1) Value = 1; |
|
163 return (Value != _options[(int)Option]); |
|
164 case TunerOption.IfShift: |
|
165 case TunerOption.Squelch: |
|
166 case TunerOption.Volume: |
|
167 return (Value != _options[(int)Option]); |
|
168 case TunerOption.RadioText: |
|
169 Value = 1; |
|
170 return true; |
|
171 default: |
|
172 return true; |
|
173 } |
|
174 } |
|
175 protected void AcceptOption(TunerOption Option, byte Value) { |
|
176 if (_options[(int)Option] != Value) { |
|
177 _options[(int)Option] = Value; |
|
178 if (OptionChanged != null) OptionChanged(this, new TunerOptionChangedEventArgs(Option)); |
|
179 } |
|
180 } |
|
181 |
|
182 protected bool CheckFrequency(ref ulong frequency, ref bool notexact) { |
|
183 ulong closest = 0; |
|
184 ulong diff = ulong.MaxValue; |
|
185 if (frequency == 0 || frequency == _frequency) { //Frequency was not changed, return current mode |
|
186 frequency = _mode; |
|
187 return false; |
|
188 } |
|
189 foreach (TunerFrequencyRange f in _capabilities.Bands) { |
|
190 if (frequency >= f.Begin && frequency <= f.End) return true; |
|
191 if (frequency < f.Begin && diff > f.Begin - frequency) { |
|
192 closest = f.Begin; |
|
193 diff = closest - frequency; |
|
194 } else if (frequency > f.End && diff > frequency - f.End) { |
|
195 closest = f.End; |
|
196 diff = frequency - closest; |
|
197 } |
|
198 } |
|
199 if (closest != 0 && closest != _frequency) { |
|
200 notexact = true; |
|
201 frequency = closest; |
|
202 return true; |
|
203 } else { |
|
204 return false; |
|
205 } |
|
206 } |
|
207 protected bool CheckMode(ref byte mode, ref bool notexact) { |
|
208 if (mode == 0 || mode == _mode) { //Mode was not changed, return current mode |
|
209 mode = _mode; |
|
210 return false; |
|
211 } |
|
212 foreach (byte b in _capabilities.AvailableModes) { //Mode was changed, accept if allowed |
|
213 if (mode == b) return true; |
|
214 } |
|
215 mode = _mode; //Mode was changed but not allowed, keep current mode |
|
216 return false; |
|
217 } |
|
218 protected bool CheckFilter(ref byte filter, ref bool notexact) { |
|
219 byte closest = 0; |
|
220 int diff = int.MaxValue; |
|
221 //Filter has to be checked against AvailableFilters, in case AvailableFilters was changed |
|
222 /*if (filter == 0 || filter == _filter) { //Filter was not changed, return current filter |
|
223 filter = _filter; |
|
224 return false; |
|
225 }*/ |
|
226 foreach (byte b in _capabilities.AvailableFilters) { //Filter was changed, find closest one |
|
227 if (filter == b) return true; |
|
228 if (filter < b && diff > b - filter) { |
|
229 closest = b; |
|
230 diff = closest - filter; |
|
231 } else if (filter > b && diff > filter - b) { |
|
232 closest = b; |
|
233 diff = filter - closest; |
|
234 } |
|
235 } |
|
236 if (closest != 0 && closest != _filter) { |
|
237 notexact = true; |
|
238 filter = closest; |
|
239 return true; |
|
240 } else { |
|
241 return false; |
|
242 } |
|
243 } |
|
244 |
|
245 protected void AcceptTuning(ulong frequency, byte mode, byte filter) { |
|
246 bool changed = false; |
|
247 if (frequency != 0 && frequency != _frequency) { changed = true; _frequency = frequency; } |
|
248 if (mode != 0 && mode != _mode) { changed = true; _mode = mode; } |
|
249 if (filter != 0 && filter != _filter) { changed = true; _filter = filter; } |
|
250 if (changed && TuningChanged != null) TuningChanged(this, new EventArgs()); |
|
251 } |
|
252 |
|
253 protected void AcceptAvailableFilters(byte[] Filters) { |
|
254 AcceptAvailableModes(null, Filters); |
|
255 } |
|
256 protected void AcceptAvailableModes(byte[] Modes, byte[] Filters) { |
|
257 if (Modes != null) _capabilities.AvailableModes = Modes; |
|
258 if (Filters != null) _capabilities.AvailableFilters = Filters; |
|
259 if (AvailableModesChanged != null) AvailableModesChanged(this, new EventArgs()); |
|
260 } |
|
261 } |
|
262 } |