comparison Radio/Tuner.cs @ 0:3ab940a0c7a0

Initial commit
author Ivo Smits <Ivo@UCIS.nl>
date Tue, 11 Sep 2012 16:28:53 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3ab940a0c7a0
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 }