Subversion Repositories group.electronics

Rev

Rev 156 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
139 pfowler 1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
155 pfowler 6
using System.Timers;
139 pfowler 7
 
155 pfowler 8
using Microsoft.FlightSimulator.SimConnect;
9
 
139 pfowler 10
using LibUsbDotNet;
11
using LibUsbDotNet.Main;
12
using LibUsbDotNet.DeviceNotify;
13
 
14
namespace NITNavComm {
15
    public class NITNavCommDevice : NITDevice  {
16
 
17
        enum UsbCommands : byte {
18
            CMD_LATCH_DISPLAY = 20,
153 pfowler 19
            CMD_SET_DISPLAY = 21,
139 pfowler 20
        };
21
 
22
        private byte[,] display { get; set; }
23
        private byte[] buttons {get; set; }
149 pfowler 24
        private sbyte[,] rotary;
155 pfowler 25
        private ushort[] points { get; set; }
139 pfowler 26
 
155 pfowler 27
        public int flipcomm { get; set; }
28
        public int flipnav { get; set; }
29
 
30
        public uint simStatus { get; set; }
31
 
156 pfowler 32
        public int comStatus { get; set; }
33
        public bool navAvailable { get; set; }
34
        public bool avionicsMaster { get; set; }
35
 
155 pfowler 36
 
37
        private const int TIMER_COUNT = 4;
38
        private const int TIMER_COMMSWAP = 0;
39
        private const int TIMER_COMMFLIP = 1;
40
        private const int TIMER_NAVSWAP = 2;
41
        private const int TIMER_NAVFLIP = 3;
42
        Timer[] timers = new Timer[TIMER_COUNT];
43
 
139 pfowler 44
        public NITNavCommDevice(NITDevice nitDevice) :
45
            base(nitDevice.usbRegistry, "NITNavComm", nitDevice.vid, nitDevice.pid) {
155 pfowler 46
            this.init();
139 pfowler 47
        }
48
 
49
        public NITNavCommDevice(UsbRegistry usbRegistry, string type, int vid, int pid) :
50
            base(usbRegistry, "NITNavComm", 0x20a0, 0x4236) {
155 pfowler 51
            this.init();
139 pfowler 52
        }
53
 
147 pfowler 54
        private void init()
55
        {
155 pfowler 56
            base.Open();
57
 
147 pfowler 58
            this.display = new byte[2, 10];
155 pfowler 59
            this.points = new ushort[2];
60
            this.blankDisplay();
61
 
147 pfowler 62
            this.buttons = new byte[2];
63
            this.buttons[0] = 0x00;
64
            this.buttons[1] = 0x00;
155 pfowler 65
 
149 pfowler 66
            this.rotary = new sbyte[2, 2];
156 pfowler 67
            this.resetAllRotary();
155 pfowler 68
 
69
            this.flipcomm = 0;
70
            this.flipnav = 0;
71
 
72
            this.simStatus = 0;
73
            this.assigned = 1;
74
 
156 pfowler 75
            this.comStatus = 0;
76
            this.navAvailable = true;
77
            this.avionicsMaster = false;
78
 
155 pfowler 79
            for (int i = 0; i < TIMER_COUNT; i++) {
80
                Timer timer = new Timer();
81
                timer.Enabled = false;
82
                timer.AutoReset = false;
156 pfowler 83
                timer.Interval = NITPanels.CFG_BUTTON_DEBOUNCE_TIME;
155 pfowler 84
                timer.Elapsed += OnDebounceTimer;
85
                timers[i] = timer;
86
            }
87
 
147 pfowler 88
        }
89
 
155 pfowler 90
        private static void OnDebounceTimer(Object source, ElapsedEventArgs e) {
91
            Timer timer = (Timer)source;
92
            timer.Enabled = false;
93
        }
94
 
156 pfowler 95
        public override bool Close() {
155 pfowler 96
            this.blankDisplay();
97
            return base.Close();
98
        }
99
 
100
        public void powerDown() {
156 pfowler 101
            this.resetAllRotary();
155 pfowler 102
            this.blankDisplay();
103
            this.simStatus = 2;
104
        }
105
 
106
        public void powerUp() {
156 pfowler 107
            this.resetAllRotary();
155 pfowler 108
            this.simStatus = 0;
156 pfowler 109
 
110
            if (this.assigned == 1)
111
                this.fsx.requestNavComm1Data();
112
            else if (this.assigned == 2)
113
                this.fsx.requestNavComm2Data();
155 pfowler 114
        }
115
 
116
        public void blankDisplay() {
139 pfowler 117
            byte[] blank = { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a };
118
            for (byte i = 0; i < 4; i++)
119
                setFreq(i, ref blank);
156 pfowler 120
            this.points[0] = 0x0000;
155 pfowler 121
            this.points[1] = 0x0000;
153 pfowler 122
            this.UpdateDisplay();
139 pfowler 123
        }
124
 
125
        public byte[] getFreq(byte freq) {
126
            byte[] ret = new byte[5];
127
            switch (freq) {
128
                case 0:
129
                    for (byte i = 0; i < 5; i++)
130
                        ret[i] = display[0, i];
131
                    break;
132
                case 1:
133
                    for (byte i = 0; i < 5; i++)
134
                        ret[i] = display[0, i + 5];
135
                    break;
136
                case 2:
137
                    for (byte i = 0; i < 5; i++)
138
                        ret[i] = display[1, i];
139
                    break;
140
                case 3:
141
                    for (byte i = 0; i < 5; i++)
142
                        ret[i] = display[1, i + 5];
143
                    break;
144
            }
145
            return ret;
146
        }
147
 
148
        public void setFreq(byte freq, ref byte[] data) {
149
            switch (freq) {
150
                case 0:
151
                    for (byte i = 0; i < 5; i++)
152
                        display[0, i] = data[i];
153
                    break;
154
                case 1:
155
                    for (byte i = 0; i < 5; i++)
156
                        display[0, i+5] = data[i];
157
                    break;
158
                case 2:
159
                    for (byte i = 0; i < 5; i++)
160
                        display[1, i] = data[i];
161
                    break;
162
                case 3:
163
                    for (byte i = 0; i < 5; i++)
164
                        display[1, i + 5] = data[i];
165
                    break;
166
            }
167
        }
168
 
155 pfowler 169
        public void setNavComFreqs(FSXObject.NavCom_Data data) {
153 pfowler 170
            byte[] freq0 = this.charArrayToBytes(data.Freq0.ToString().ToCharArray());
171
            byte[] freq1 = this.charArrayToBytes(data.Freq1.ToString().ToCharArray());
172
            byte[] freq2 = this.charArrayToBytes(data.Freq2.ToString().ToCharArray());
173
            byte[] freq3 = this.charArrayToBytes(data.Freq3.ToString().ToCharArray());
174
 
175
            this.setFreq(0, ref freq0);
176
            this.setFreq(1, ref freq1);
177
            this.setFreq(2, ref freq2);
178
            this.setFreq(3, ref freq3);
179
 
180
            this.UpdateDisplay();
181
        }
182
 
183
        private byte[] charArrayToBytes(char[] digits) {
184
            byte[] bytes = new byte[5];
185
            for (byte i = 0; i < 5; i++) {
186
                bytes[i] = (byte)(digits[i] - '0');
187
            }
188
            return bytes;
189
        }
190
 
191
        public void setDisplay(byte dis, ref byte[] data) {
192
            for (byte i = 0; i < data.Length; i++) {
193
                display[dis, i] = data[i];
194
            }
195
        }
196
 
139 pfowler 197
        private void sendDigit(byte dis, byte dig, byte val, byte dp) {
198
            ushort wxValue = (ushort)(dis <<8);
199
            wxValue |= dig;
200
            ushort wxIndex = (ushort)(dp << 8);
201
            wxIndex |= val;
202
 
203
            base.SendCommand(21, (short)wxValue, (short)wxIndex);
204
        }
205
 
206
        private void sendLatch(byte dis) {
153 pfowler 207
            if (!this.isOpen())
208
                return;
209
 
139 pfowler 210
            base.SendCommand(20, (short)dis, 0);
211
        }
212
 
213
        public void updateInput() {
214
            byte[] data = new byte[8];
215
            int transferred;
149 pfowler 216
            base.SendCommand(30, 0, 0, data, out transferred);
217
            this.buttons[0] = data[0];
218
            this.rotary[0, 0] += (sbyte)data[1];
219
            this.buttons[1] = data[2];
220
            this.rotary[1, 0] += (sbyte)data[3];
139 pfowler 221
        }
222
 
223
        public bool isSwapSet(byte dis) {
224
            if ((this.buttons[dis] & 0x01)>0)
225
                return true;
226
            return false;
227
        }
228
 
229
        public bool isFlipSet(byte dis) {
230
            if ((this.buttons[dis] & 0x02) > 0)
231
                return true;
232
            return false;
233
        }
234
 
149 pfowler 235
        public sbyte getRotary(byte dis, byte rotary) {
139 pfowler 236
            return this.rotary[dis, rotary];
237
        }
238
 
149 pfowler 239
        public void resetRotary(byte display, byte rotary) {
240
            this.rotary[display, rotary] = 0x00;
241
        }
242
 
156 pfowler 243
        public void resetAllRotary() {
244
            this.rotary[0, 0] = 0x00;
245
            this.rotary[0, 1] = 0x00;
246
            this.rotary[1, 0] = 0x00;
247
            this.rotary[1, 1] = 0x00;
248
        }
249
 
155 pfowler 250
        private void sendData(byte dis) {
251
            for (byte i = 0; i < 10; i++) {
252
                //this.sendDigit(dis, i, display[dis, i], this.GetBit(this.points[dis], i));
253
                this.sendDigit(dis, i, display[dis, i], 0);
254
            }            
255
        }
256
 
153 pfowler 257
        public void UpdateDisplay() {
258
            this.sendData(0);
259
            this.sendData(1);
260
            this.latchDisplay(0);
261
            this.latchDisplay(1);
139 pfowler 262
        }
263
 
153 pfowler 264
        public void UpdateDisplay(byte dis) {
265
            this.sendData(dis);
266
            this.latchDisplay(dis);
267
        }
268
 
155 pfowler 269
        private byte GetBit(ushort b, byte bitNumber) {
270
            if ((b & (1 << bitNumber)) != 0)
271
                return 1;
272
            return 0;
153 pfowler 273
        }
274
 
275
        private void latchDisplay(byte dis) {
139 pfowler 276
            this.sendLatch(dis);
277
        }
278
 
279
        public void swapFreq(byte display) {
280
            if (display == 0) {
281
                byte[] left = this.getFreq(0);
282
                byte[] right = this.getFreq(1);
283
                this.setFreq(0, ref right);
284
                this.setFreq(1, ref left);
285
            } else if (display == 1) {
286
                byte[] left = this.getFreq(2);
287
                byte[] right = this.getFreq(3);
288
                this.setFreq(2, ref right);
289
                this.setFreq(3, ref left);
290
            }
291
        }
156 pfowler 292
 
157 pfowler 293
        public override void FsxInit() { }
156 pfowler 294
 
157 pfowler 295
        public override void MapEvents() {
296
 
156 pfowler 297
 
298
        }
299
 
157 pfowler 300
        public override void FsxEvent(SIMCONNECT_RECV_SIMOBJECT_DATA data) {
156 pfowler 301
 
302
            if (data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.AVIONICS) {
303
 
304
                FSXObject.Avionics_Data avionics = (FSXObject.Avionics_Data)data.dwData[0];
305
 
306
                this.avionicsMaster = avionics.avionics_master;
307
                if (this.assigned == 1)
308
                    this.comStatus = (int)avionics.com1_status;
309
                else
310
                    this.comStatus = (int)avionics.com2_status;
311
 
312
                if (this.assigned == 1)
313
                    this.navAvailable = avionics.nav1_available;
314
                else if (this.assigned == 2)
315
                    this.navAvailable = avionics.nav2_available;
316
 
317
                if (!this.avionicsMaster || this.comStatus != 0) {
318
                    this.powerDown();
319
                    return;
320
                }
321
 
322
                if (this.avionicsMaster && this.comStatus == 0 && this.simStatus != 0) {
323
                    this.powerUp();
324
                    return;
325
                }
326
            }
327
 
328
            if (this.simStatus != 0)
329
                return;
330
 
331
            if (this.assigned == 1 && data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.NAVCOM1_REQ) {
332
                FSXObject.NavCom_Data navcomdata = (FSXObject.NavCom_Data)data.dwData[0];
333
                this.setNavComFreqs(navcomdata);
334
            } else if (this.assigned == 2 && data.dwRequestID == (uint)FSXObject.DATA_REQUESTS.NAVCOM2_REQ) {
335
                FSXObject.NavCom_Data navcomdata = (FSXObject.NavCom_Data)data.dwData[0];
336
                this.setNavComFreqs(navcomdata);
337
            }
338
 
339
        }
340
 
157 pfowler 341
        public override void FsxReady() {
156 pfowler 342
 
343
        }
344
 
345
 
155 pfowler 346
        // @TODO: Make this work with COMM1/COMM2
157 pfowler 347
        public override void SimButtons() {
156 pfowler 348
 
349
            if (this.simStatus != 0)
350
                return;
351
 
352
            this.updateInput();
155 pfowler 353
 
354
            if (!timers[TIMER_COMMSWAP].Enabled && this.isSwapSet(0)) {
355
                if (this.assigned == 1)
356
                    fsx.Comm1SwapFreq();
357
                else
358
                    fsx.Comm2SwapFreq();
359
                timers[TIMER_COMMSWAP].Enabled = true;
360
            }
361
 
362
            if (!timers[TIMER_NAVSWAP].Enabled && this.isSwapSet(1)) {
363
                if (this.assigned == 1)
364
                    fsx.Nav1SwapFreq();
365
                else
366
                    fsx.Nav2SwapFreq();
367
 
368
                timers[TIMER_NAVSWAP].Enabled = true;
369
            }
370
 
371
            // Check if the MHz/KHz has been pressed
372
            if (!timers[TIMER_COMMFLIP].Enabled && this.isFlipSet(0)) {
373
                this.flipcomm = 1 - this.flipcomm;
374
                timers[TIMER_COMMFLIP].Enabled = true;
375
            }
376
 
377
            if (!timers[TIMER_NAVFLIP].Enabled && this.isFlipSet(1)) {
378
                this.flipnav = 1 - this.flipnav;
379
                timers[TIMER_NAVFLIP].Enabled = true;
380
            }
381
 
382
            // Process the rotary encoders COMM1
383
            sbyte delta = this.getRotary(0, 0);
384
            this.resetRotary(0, 0);
385
            if (delta != 0) {
386
                if (delta < 0) {
387
                    delta = (sbyte)-delta;
388
 
389
                    if (this.flipcomm == 1)
390
                        if (this.assigned == 1)
391
                            fsx.Comm1DecFract();
392
                        else
393
                            fsx.Comm2DecFract();
394
                    else
395
                        if (this.assigned == 1)
396
                            fsx.Comm1DecWhole();
397
                        else
398
                            fsx.Comm2DecWhole();
399
                } else {
400
 
401
                    if (this.flipcomm == 1)
402
                        if (this.assigned == 1)
403
                            fsx.Comm1IncFract();
404
                        else
405
                            fsx.Comm2IncFract();
406
                    else
407
                        if (this.assigned == 1)
408
                            fsx.Comm1IncWhole();
409
                        else
410
                            fsx.Comm2IncWhole();
411
                }
412
            }
413
 
414
            // Process the rotary encoders NAV1
415
            delta = this.getRotary(1, 0);
416
            this.resetRotary(1, 0);
417
            if (delta != 0) {
418
                if (delta < 0) {
419
                    delta = (sbyte)-delta;
420
 
421
                    if (this.flipnav == 1)
422
                        if (this.assigned == 1)
423
                            fsx.Nav1DecFract();
424
                        else
425
                            fsx.Nav2DecFract();
426
                    else
427
                        if (this.assigned == 1)
428
                            fsx.Nav1DecWhole();
429
                        else
430
                            fsx.Nav2DecWhole();
431
                } else {
432
 
433
                    if (this.flipcomm == 1)
434
                        if (this.assigned == 1)
435
                            fsx.Nav1IncFract();
436
                        else
437
                            fsx.Nav2IncFract();
438
                    else
439
                        if (this.assigned == 1)
440
                            fsx.Nav1IncWhole();
441
                        else
442
                            fsx.Nav2IncWhole();
443
                }
444
            }
445
 
446
        }
139 pfowler 447
    }
448
}