Mercurial > hg > ucis.core
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 } |